Почему я не могу сказать, что `I <class>это я`? - PullRequest
1 голос
/ 17 марта 2011

У меня есть эта настройка в моем коде:

public abstract class ModelBase{}
public interface IModelbase<T>{}
public abstract class ModelBase<T> : ModelBase, IModelBase<T> {}
public class MyClass : ModelBase<int> {}

А потом мне дают объект FutureValue<MyClass> от NHibernate, и я пытаюсь:

if (obj is IFutureValue<ModelBase>) // => false?
// or
if (obj is FutureValue<ModelBase>) // => false?
// (I changed NHibernate's source to make FutureValue public, for other uses)

Между тем, если я приведу его к типу напрямую:

if (((IFutureValue<MyClass>)obj).Value is ModelBase) // => true!
// or
if (((FutureValue<MyClass>)obj).Value is ModelBase) // => true!

... серьезно?Это в цепочке наследования, есть ли какая-то причина, по которой он не просматривается?Проверка объекта в отладчике показывает, что это на самом деле MyClass, и на нем есть методы и свойства ModelBase, поэтому я сомневаюсь, что это как-то связано с прокси-сервером NHibernate.

Почему бы .NET не искать наследованиецепи в такой ситуации?Есть ли какой-нибудь трюк с ключевыми словами / кастингом, который я могу выполнить, чтобы заставить его это сделать?Или я должен прибегнуть к большой неуклюжей установке, подобной:

if (obj is IFutureValue<MyClass>) return ((IFutureValue<MyClass>)obj).Value;
if (obj is IFutureValue<MyOtherClass>) return ((IFutureValue<MyOtherClass>)obj).Value;
// etc etc ad infinitum

edit: это в .NET 2.0


edit2: точный код (I)FutureValue:

public interface IFutureValue<T>
{
    T Value { get; }
}
public class FutureValue<T> : IFutureValue<T>
{
    public delegate IList<T> GetResult();

    private readonly GetResult getResult;

    public FutureValue(GetResult result)
    {
        getResult = result;
    }

    public T Value
    {
        get
        {
            var result = getResult();

            if (result.Count == 0)
            {
                return default(T);
            }

            return result[0];
        }
    }
}

Я просто очень неправильно понимаю проблему ковариации / контравариантности (в этом случае, почему Func<Type2, Type2> f1 = MyMethod; может быть приведено к Func<Type3, Type1> f2 = f1; (где первый тип - тип возвращаемого значения), но вышекод не может сделать то же самое? Если только .NET 2.0 не работает с полиморфизмом?


edit3: мышление при наборе текста. Это потому, что IList<T> определяет делегатов, которые принимают, скажем, производный тип, поэтомунужен Derived или DoublyDerived T, но тип возвращаемого значения может быть только T или Base? Поэтому я не могу разыграть ни одно из направлений ... Интересно, смогу ли я убедить NHibernate переключиться на IEnumerable<T> в их Futures ... это решитэто?

1 Ответ

2 голосов
/ 17 марта 2011

IFutureValue<T> - это общий интерфейс с типом параметра Ковариант . Похоже, вы ожидаете поведение Contravariant параметра универсального типа. Для получения дополнительной информации прочитайте документацию MSDN по Ковариантность и Контравариантность в обобщениях

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