Введите ограничения на реализации универсальных членов неуниверсальных интерфейсов в C#

Скажем, у меня есть интерфейс как этот:

interface IAwesome
{
    T DoSomething();
}

Там какой-либо путь состоит в том, чтобы реализовать метод DoSomething с ограничением типа? Очевидно, это не будет работать:

class IncrediblyAwesome : IAwesome where T : PonyFactoryFactoryFacade
{
    public T DoSomething()
    {
        throw new NotImplementedException();
    }
}

Это, очевидно, не будет работать, потому что этот DoSomething () не полностью удовлетворит контракт IAwesome - он только работает на подмножество всех возможных значений параметра типа T. Там какой-либо путь состоит в том, чтобы получить эту работу за исключением некоторой "черной магии кастинга" (который является тем, что я собираюсь сделать как последнее средство, если ответ не)?

Честно, я не думаю, что это возможно, но интересно, что Вы думают парни.

Править: Рассматриваемым интерфейсом является Система. Linq. IQueryProvider, таким образом, я не могу изменить сам интерфейс.

8
задан Tamas Czinege 13 February 2010 в 21:29
поделиться

3 ответа

Нет, это не может работать по замыслу, поскольку это означало бы, что контракт на 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();
    }
}
7
ответ дан 5 December 2019 в 17:37
поделиться

Не сработает ли что-то вроде этого?

interface IAwesome<U>
{
    T DoSomething<T>() where T : U
}

class IncrediblyAwesome<T> : IAwesome<PonyFactoryFactoryFacade>
{
    public T DoSomething()
    {
        throw new NotImplementedException();
    }
}

Я не уверен, что это компилируется.

2
ответ дан 5 December 2019 в 17:37
поделиться

Как вы уже сказали, такое решение не может работать.

Более того, ваш пример нарушает договор другим способом: один экземпляр IncredibleAwesome всегда привязан к одному конкретному потомку PonyFactoryFactoryFacade (кстати, я бы действительно был интересует цель этого класса :-)). Следовательно, конкретная реализация DoSomething будет не универсальным методом, как указано в интерфейсе, но всегда будет возвращать один единственный тип. Вы не можете писать:

IAwesome a = new IncrediblyAwesome<SomePonyFacadeFactory1>();
SomePonyFacadeFactory2 facade2 = a.DoSomething<SomePonyFacadeFactory2>();

хотя обе фабрики фасадов происходят от PonyFactoryFactoryFacade ...

Еще один комментарий: я бы держался подальше от использования черной магии, поскольку эти проблемы присущи вашему дизайну и не только недостаток C # ...

1
ответ дан 5 December 2019 в 17:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: