c# - 无效参数 - 继承的接口(interface)有效,但隐式转换则不然。是什么赋予了?

标签 c# linq interface

我有一个函数,其签名为

Update(IEnumberable<INotifyPropertyChanging> things)

和一个类

doohickey : INotifyPropertyChanging, INotifyPropertyChanging{}

当我尝试做

List<doohickey> doohickeys = new List<doohickey>();
Update(doohickeys);

抛出异常,说明:

cannot convert from 'System.Collections.Generic.List<doohickey>' to 'System.Collections.Generic.IEnumerable<System.ComponentModel.INotifyPropertyChanging>'

什么给出了? Doohickey继承了INotifyPropertyChanging接口(interface),List继承了IEnumerable接口(interface)!为什么简单地传递对象并期望它被强制转换却不会呢?

我添加了对 INotifyPropertyChanging 的引用,以表明 doohickey 实际上是一个 linq-to-sql 类;万一上下文很重要。

最佳答案

这不起作用,因为 List<doohickey> 之间没有隐式转换。和IEnumerable<NotifyPropertyChanging> 。您需要调用:

Update(doohickeys.Cast<INotifyPropertyChanging>());

这背后的原因是类型安全。在 C#4 中,语言中添加了协/逆变,这通常有助于使这些类型的转换有效。但有一些限制,因为涉及的类型需要声明为协变/逆变,并且它仅适用于接口(interface)和委托(delegate)。

无法隐式转换的原因List<T>List<TBase>也就是说,它将使此代码有效:

List<T> values = new List<T>();
// add some values...
List<TBase> bases = values;
bases.Add(new TBase());  // Woops. We broke type safety by adding a TBase to a list of T's

现在,如果您尝试在 values 时执行此操作类型为IEnumerable<T> ,这在 C#4 中是有效的。这是因为您只能IEnumerable<T> 中获取值 ,所以我们不需要担心添加较少的类型。因此IEnumerable<T>是协变的,并且声明为:

IEnumerable<out T>

哪里out意思是“协变”。 (关键字实际上是记住变体类型中值的走向的最佳方式。

协方差/逆变是一个相当大的主题,but this article does a good job of explaining the most important parts 。如果您想了解更多信息,Eric Lippert 有一个 11-part blog post series关于该功能。 Eric 是语言设计师之一。

关于c# - 无效参数 - 继承的接口(interface)有效,但隐式转换则不然。是什么赋予了?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4493686/

相关文章:

c# - 根据条件从函数调用 JavaScript

c# - 在linq中将多列求和并分组为一个值

c# - 使用 LINQ IEnumerable.ToDictionary() 时无法将类隐式转换为基类

java - 接口(interface)对象和类对象的区别

COM 服务器缺少接口(interface)

c# - 寻找类似 HashSet 的东西,但具有一系列键值?

c# - Linq to SQL - 在 Html.TextBoxFor 中格式化 DateTime

c# - CUDAfy模块的性能

c# - 如何在Linq查询中的选择条件中放置where条件

java - Eclipse 希望实现不存在的方法