Скажем, у меня есть интерфейс как этот:
interface IAwesome
{
T DoSomething();
}
Там какой-либо путь состоит в том, чтобы реализовать метод DoSomething с ограничением типа? Очевидно, это не будет работать:
class IncrediblyAwesome : IAwesome where T : PonyFactoryFactoryFacade
{
public T DoSomething()
{
throw new NotImplementedException();
}
}
Это, очевидно, не будет работать, потому что этот DoSomething () не полностью удовлетворит контракт IAwesome - он только работает на подмножество всех возможных значений параметра типа T. Там какой-либо путь состоит в том, чтобы получить эту работу за исключением некоторой "черной магии кастинга" (который является тем, что я собираюсь сделать как последнее средство, если ответ не)?
Честно, я не думаю, что это возможно, но интересно, что Вы думают парни.
Править: Рассматриваемым интерфейсом является Система. Linq. IQueryProvider, таким образом, я не могу изменить сам интерфейс.
Нет, это не может работать по замыслу, поскольку это означало бы, что контракт на IAwesome
не будет (полностью) выполнен.
Пока IncrediblyAwesome
реализует IAwesome
, это можно делать:
IAwesome x = new IncrediblyAwesome<Something>()
Очевидно, что с вашим дополнительным ограничением это не может работать, поскольку пользователь IAwesome
не может знать о наложенных на него ограничениях.
В вашем случае единственным решением, которое я могу предложить, является следующее (выполнение проверки во время выполнения):
interface IAwesome { // assuming the same interface as in your sample
T DoSomething<T>();
}
class IncrediblyAwesome<TPony> : IAwesome where TPony : PonyFactoryFactoryFacade {
IAwesome.DoSomething<TAnything>() {
return (TAnything)((object)DoSomething()); // or another conversion, maybe using the Convert class
}
public TPony DoSomething() {
throw new NotImplementedException();
}
}
Не сработает ли что-то вроде этого?
interface IAwesome<U>
{
T DoSomething<T>() where T : U
}
class IncrediblyAwesome<T> : IAwesome<PonyFactoryFactoryFacade>
{
public T DoSomething()
{
throw new NotImplementedException();
}
}
Я не уверен, что это компилируется.
Как вы уже сказали, такое решение не может работать.
Более того, ваш пример нарушает договор другим способом: один экземпляр IncredibleAwesome
всегда привязан к одному конкретному потомку PonyFactoryFactoryFacade
(кстати, я бы действительно был интересует цель этого класса :-)). Следовательно, конкретная реализация DoSomething
будет не универсальным методом, как указано в интерфейсе, но всегда будет возвращать один единственный тип. Вы не можете писать:
IAwesome a = new IncrediblyAwesome<SomePonyFacadeFactory1>();
SomePonyFacadeFactory2 facade2 = a.DoSomething<SomePonyFacadeFactory2>();
хотя обе фабрики фасадов происходят от PonyFactoryFactoryFacade
...
Еще один комментарий: я бы держался подальше от использования черной магии, поскольку эти проблемы присущи вашему дизайну и не только недостаток C # ...