[英]How can I create a covariant extension method on a generic interface in C#?
如果标题没有意义,这是一个例子:
interface IEat { void Eat; }
class Cat : IEat { void Eat { nom(); } }
class Dog : IEat { void Eat { nom(); nom();nom(); } }
class Labrador : Dog { }
我想创建一个像这样的扩展方法:
public static void FeedAll(this IEnumerable<out IEat> hungryAnimals) {
foreach(var animal in hungryAnimals) animal.Eat();
}
所以我可以这样做:
listOfCats.FeedAll();
listOfLabs.FeedAll();
listOfMixedHungryAnimals.FeedAll();
这可能吗? 我哪里做错了?
这里真实的应用程序是“Dog”是我的应用程序中的主要基类,并且有许多子类,每个子类可能不时有IList,需要对它们执行组操作。 必须将它们转换为在它们全部实现的接口List上调用扩展方法将是次优的。
编辑:
我稍微讨论了这个例子。 我的实际代码是使用IList
,我希望可以使用Count和基于索引的操作。 基于下面的答案,我想我将不得不为需要IList语义的方法寻找另一个方向。
这将删除out
:
public static void FeedAll(this IEnumerable<IEat> hungryAnimals) {
foreach(var animal in hungryAnimals) animal.Eat();
}
方差应用于接口本身(的参数T
中IEnumerable<T>
在这种情况下),这样一个List<Dog>
是兼容IEnumerable<IEat>
IEnumerable
已经是协变的,因此您的扩展方法可以接受IEnumerable<IEat>
,并且IEnumerable<Dog>
实例将是一个有效的参数,使得扩展方法适用于这些类型的变量。
如果接口的定义没有指定泛型参数是协变/逆变,那么扩展方法可以做的任何事情都不允许该参数是协变的。 如果您使用的是一个不变的List
,那么您的扩展方法无法允许使用协方差。
正如Servy所说, Enumerable<T>
已经是协变的,但它并不需要。 对于界面不协变的旧版本,您可以这样做:
public static void FeedAll<T>(this IEnumerable<T> hungryAnimals) where T : IEat
{
foreach(var animal in hungryAnimals) animal.Eat();
}
你不需要它通过引用传递它所以它将解决它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.