Ковариантное использование универсального класса Lazy в C#

Предполагая, что это применимо:

public class Cat : Animal { }

и предполагая, что у меня есть метод:

public void Feed(Animal animal) { ... }

И я могу назвать это так:

var animal = new Cat();
Feed(animal);

Как я могу заставить это работать, когда Feed рефакторинг поддерживает только Lazy<Animal> в качестве параметра? Я хотел бы как-нибудь передать свой var lazyAnimal = new Lazy<Cat>();.

Это явно не работает:

var lazyAnimal = new Lazy<Cat>();
Feed(lazyAnimal);

person thmshd    schedule 14.01.2014    source источник


Ответы (2)


Ну, вы не сможете использовать его именно так, как есть. Вероятно, самым простым рефакторингом было бы принять Func<Animal> вместо Lazy. Затем вы можете передать лямбду, которая извлекает значение Lazy. Func является ковариантным по отношению к типу возвращаемого значения.

person Servy    schedule 14.01.2014

Вы не можете, в принципе, не напрямую, во всяком случае. Lazy<T> - это класс, поэтому не предполагает общей дисперсии.

Вы можете создать свой собственный ILazy<out T> интерфейс, реализовать его используя Lazy<T>, а затем вместо этого заставить Feed использовать ILazy<Animal>. Реализация будет тривиальной.

В качестве альтернативы вы можете сделать Feed универсальным:

public void Feed<T>(Lazy<T> animal) where T : Animal

Или предложение Серви взять Func<Animal> тоже сработает, и вы можете вызвать его, используя лямбда-выражение для Lazy<T>:

Feed(() => lazyAnimal.Value);
person Jon Skeet    schedule 14.01.2014
comment
Спасибо пока; Я должен был упомянуть (я хотел, чтобы это было просто), что этот класс на самом деле является конструктором? :) Это больше похоже на... FeedMachine, который я не могу сделать общим. Однако я бы проверил подход Func. - person thmshd; 14.01.2014
comment
@thomasjaworski.com: Не уверен, что вы подразумеваете, что этот класс на самом деле является конструктором - вы имеете в виду этот метод? Вы всегда можете написать статический общий метод, который вызывает конструктор... - person Jon Skeet; 14.01.2014