首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >这是C# 4中的协方差错误吗?

这是C# 4中的协方差错误吗?
EN

Stack Overflow用户
提问于 2010-05-06 17:49:05
回答 2查看 1.8K关注 0票数 37

在下面的代码中,我希望能够隐式地从elements转换到baseElements,因为TBase可以隐式转换为IBase

代码语言:javascript
复制
public interface IBase { }
public interface IDerived : IBase { }
public class VarianceBug
{
    public void Foo<TBase>() where TBase : IBase
    {
        IEnumerable<TBase> elements = null;
        IEnumerable<IDerived> derivedElements = null;
        IEnumerable<IBase> baseElements;

        // works fine
        baseElements = derivedElements;

        // error CS0266: Cannot implicitly convert type 
        //   'System.Collections.Generic.IEnumerable<TBase>' to 
        //   'System.Collections.Generic.IEnumerable<IBase>'. 
        //   An explicit conversion exists (are you missing a cast?)
        baseElements = elements;
    }
}

但是,我得到了注释中提到的错误。

引用规范的话:

类型T<A1, …, An>是可转换为类型T<B1, …, Bn>的类型,如果T是一个接口或一个委托类型,并声明了变量类型参数T<X1, …, Xn>,并且对于每个变量类型参数Xi,有以下一种情况:

  • Xi是协变的,从AiBi

存在隐式引用或身份转换。

  • Xi是反变体,从BiAi

存在隐式引用或身份转换。

  • Xi是不变的,从AiBi

存在身份转换。

检查我的代码,它似乎与规范一致:

  • IEnumerable<out T>是一种接口类型

  • IEnumerable<out T>是用可变类型参数

声明的。

  • T是协变

IBase

  • 的隐式引用转换

那么--这是C# 4编译器中的一个bug吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-05-06 18:16:23

方差只适用于引用类型(或存在身份转换)。除非添加TBase,否则不知道: class是引用类型。

代码语言:javascript
复制
 public void Foo<TBase>() where TBase : class, IBase

因为我可以写一个:

代码语言:javascript
复制
public struct Evil : IBase {}
票数 51
EN

Stack Overflow用户

发布于 2010-05-06 18:20:26

马克是对的-我正要贴同样的回复。

参见协方差和反方差常见问题:

http://blogs.msdn.com/csharpfaq/archive/2010/02/16/covariance-and-contravariance-faq.aspx

从常见问题:

“只有当类型参数是引用类型时,才支持方差。”

值类型不支持方差

以下内容也没有编译:

代码语言:javascript
复制
// int is a value type, so the code doesn't compile.
IEnumerable<Object> objects = new List<int>(); // Compiler error here.
票数 14
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2783233

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档