Подтвердить что ты не робот

Тип интерфейса литья в Lazy <T>

Мне нужно что-то вроде этого:

public interface IAnimal
{ }

public class Dog : IAnimal
{
    public Dog() {}
}

public class Cat : IAnimal
{
    public Cat() {}
}

public abstract class TestClassBase
{
    public TestClassBase()
    {
        _lazyAnimal = CreateLazyAnimal();
    }

    private Lazy<IAnimal> _lazyAnimal = null;
    public IAnimal Animal
    {
        get
        { 
            IAnimal animal = null;
            if (_lazyAnimal != null)
                animal = _lazyAnimal.Value;

            return animal;
        }
    }

    // Could be overridden to support other animals
    public virtual Lazy<IAnimal> CreateLazyAnimal()
    {
        // default animal is a dog
        return new Lazy<Dog>(); // this type of casting doesn't work and I don't know a good workground
    }
}

Я знаю, что с помощью MEF мне удается найти и хранить разные типы, реализующие один интерфейс, в Lazy <T> . Просто не уверен, как это сделать сам.

4b9b3361

Ответ 1

Lazy<Dog> не может быть преобразован непосредственно в Lazy<IAnimal>, но поскольку Dog можно преобразовать в IAnimal, вы можете использовать конструктор Lazy<IAnimal>

Ответ 2

Отбрасывание Lazy<Dog> в Lazy<IAnimal> не допускается, поскольку типы различны (тип Lazy<T> наследуется только от object). В некоторых случаях литье может иметь смысл - например, отбрасывание IEnuerable<Dog> до IEnumerable<IAnimal>, но литье не является безопасным во всех случаях.

С# 4.0 добавляет поддержку для этого литья в безопасном случае. Это называется ковариацией и контравариантностью. Например, эта статья дает хороший обзор.

К сожалению, в С# 4.0 это работает только для интерфейсов и делегатов, а не для конкретных классов (например, Lazy<T>). Вероятно, вы решили проблему, создав интерфейс ILazy<out T> и оболочку для стандартного типа Lazy, но, вероятно, проще просто написать преобразование с Lazy<Dog> на Lazy<IAnimal>.