2014-01-14 3 views
3

Предполагая, что это применимо:Ковариантное использование универсального класса Ленивый в 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); 

ответ

6

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

11

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

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

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

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

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

Feed(() => lazyAnimal.Value); 
+0

Спасибо, Я должен был упомянуть (я хотел, чтобы все было просто), что этот класс на самом деле является конструктором? :) Это больше похоже ... «FeedMachine», который я не могу сделать родовым. Однако я бы проверял подход 'Func'. – thmshd

+0

@ thomasjaworski.com: Не уверен, что вы подразумеваете под «этот класс на самом деле является конструктором» - вы имеете в виду этот метод? Вы всегда можете написать статический универсальный метод, который называется конструктором ... –