C #: неуниверсальные классы, использующие универсальные классы undefined - PullRequest
1 голос
/ 27 февраля 2011

У меня есть общий интерфейс

public interface TheInterface<T> where T : IObject

У меня также есть класс объектов, с которым этот интерфейс работает

public class SomeObject : IObject

У меня есть класс, который реализует интерфейс

public class ClassThatWorksWithSomeObject : TheInterface<SomeObject>

Все это работает достаточно хорошо.Позже я добавлю класс, который работает с классом TheInterface, независимо от того, какую версию IObject он использует.

public class IDoStuffToInterface
{
    public IDoStuffToInterface(TheInterface<IObject> interface)
    {
         //bla bla
    }
}

Проблема в том, что я не могу передать туда ClassThatWorksWithSomeObject, даже если он наследует от интерфейса иэто общий объект наследует от IObject.

Я думаю, есть некоторые случаи, когда это может быть вредно, если бы это произошло, но я не могу думать ни о каком.

Есть ли способсделать это лучше?

Ответы [ 5 ]

1 голос
/ 17 мая 2012

Другой способ, о котором я упоминал, упомянутый tvanfosson, - сделать ваш класс IDoStuffToInterface универсальным. Это также хорошо работает, если (как показано в примере) объект TheInterface передается в конструктор и (предположительно) сохраняется в классе.

Однако, если бы это была просто функция (или даже конструктор), которая использует TheInterface, и она не сохраняется в классе , вероятно, было бы лучше сделать саму функцию универсальной и оставить класс в покое. Например:

public class IDoStuffToInterface
{
    public void DoSomething<T>(TheInterface<T> theInterface) where T : IObject
    {
        //bla bla
    }
}

Это позволит вам сделать следующее:

ClassThatWorksWithSomeObject myObject = new ClassThatWorksWithSomeObject();
IDoStuffToInterface actor = new IDoStuffToInterface();
actor.DoSomething(myObject);

Это компилируется без каких-либо проблем, потому что компилятор может определить по выводу, что вы на самом деле вызываете

actor.DoSomething<SomeObject>(myObject);

Теперь я думаю, что использование ковариации все еще, вероятно, лучший вариант, если вы контролируете определение интерфейса. Но я хотел добавить это как еще один вариант, когда у вас нет такого уровня контроля в вашем интерфейсе.

1 голос
/ 27 февраля 2011

Вы должны быть в состоянии сделать это в C # 4.0, пометив тип интерфейса как контравариантный, но я думаю, что вы также можете обойти это, сделав также универсальный IDoStuffInterface.

public class IDoStuffToInterface<T> where T : IObject
{
    public IDoStuffToInterface(TheInterface<T> interface)
    {
         //bla bla
    }
}

Поскольку SomeObject соответствует T, а ClassThatWorksWithSomeObject реализует TheInterface<SomeObject>, это должно быть приемлемо в качестве параметра.

1 голос
/ 27 февраля 2011

Я думаю, что то, что вы делаете, должно работать, но вам может понадобиться использовать ковариационные и контравариантные ключевые слова .

1 голос
/ 27 февраля 2011

Вам необходимо указать ковариантное TheInterface, чтобы оно принимало более широкие типы IObject:

public interface TheInterface<out T> where T : IObject
1 голос
/ 27 февраля 2011

Я не знаю детали реализации, вы можете попробовать:

public interface TheInterface<out T> where T : IObject 

, если вы используете C # 4.0

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...