Есть ли способ реализовать эту иерархию типов, используя новый co / contravariance в C # 4? - PullRequest
0 голосов
/ 20 июня 2011

Предположим, у меня есть класс дескриптора, такой как:

interface IHasHandle<TObject> {
     IHandle<TObject> Handle { get; }
}

interface IHandle<out TObject> {
     TObject Value { get; }
}

Я хотел бы использовать этот класс, чтобы дать мне самый производный тип вывода в иерархии.То, что у меня сейчас выглядит, выглядит так:

interface IAnimal : IHasHandle<IAnimal> { ... }

interface IMammal : IAnimal, IHasHandle<IMammal> { ... }

interface IFeline : IMammal, IHasHandle<IFeline> { ... }

class Tiger : IFeline {
     IHandle<IAnimal> IHasHandle<IAnimal>.Handle { get { ... } }
     IHandle<IMammal> IHasHandle<IMammal>.Handle { get { ... } }
     IHandle<IFeline> IHasHandle<IFeline>.Handle { get { ... } }
     public IHandle<Tiger>   Handle { get { ... } }
}

Это означает, что когда у меня есть IAnimal, я всегда могу получить IHandle, когда у меня IMammal, я могу получить IHandle и т. Д.

У кого-нибудь есть общие замечания по этой структуре или идеи о том, как избежать всевозможных реализаций?

1 Ответ

0 голосов
/ 14 февраля 2012

Еще до .NET 4.0 можно было делать что-то вроде:

interface IAnimal<TSpecies> : IHasHandle<TSpecies> where TSpecies : IAnimal<TSpecies> { ... }

interface IMammal<TSpecies> : IAnimal<TSpecies> where TSpecies : IMammal<TSpecies> { ... }

interface IFeline<TSpecies> : IMammal<TSpecies> where TSpecies : IFeline<TSpecies> { ... }

class Tiger : IFeline<Tiger> {
    IHandle<Tiger> IHasHandle<Tiger>.Handle { get { ... } }
}

Конечно, это не помешает вам сделать class EvilCat : IFeline<Tiger>, но это достаточно хороший способ получитьизбавиться от лишних Handle реализаций в Tiger.И если вы объявите IHasHandle универсальный параметр как out единицу в этом примере кода, вы сможете преобразовать Tiger (который реализует IHasHandle<Tiger>) в IHasHandle<IMammal>, например.

...