协变和逆变
来源:互联网 发布:治愈动漫电影知乎 编辑:程序博客网 时间:2024/05/01 15:18
协变和逆变都是术语,前者指能够使用比原始指定的派生类型的派生程度更大的类型,后者指能够使用比原始指定的派生类型的派生程度更小的类型。
using System;
using System.Collections.Generic;using System.Text;
namespace ConsoleApplication1
{
class Program
{
class Base
{
public static void PrintBases(IEnumerable<Base> bases)
{
foreach (Base b in bases)
{
Console.WriteLine(b);
}
}
}
class Derived : Base
{
}
static void Main(string[] args)
{
List<Derived> dlist = new List<Derived>();
Derived.PrintBases(dlist);
IEnumerable<Base> bIEnum = dlist;
}
}
}
VS2008报错
错误 2 参数“1”: 无法从“System.Collections.Generic.List<ConsoleApplication1.Program.Derived>”转换为“System.Collections.Generic.IEnumerable<ConsoleApplication1.Program.Base>”
VS2010正常。
为什么呢 原来接口实现了协变
public interface IEnumerable<T> : IEnumerable
public interface IEnumerable<outT> : IEnumerable
vs2010不一样了
从 .NET Framework 4 开始,某些泛型接口具有协变类型参数;例如:IEnumerable<T>、IEnumerator<T>、IQueryable<T> 和 IGrouping<TKey, TElement>。 由于这些接口的所有类型参数都是协变类型参数,因此这些类型参数只用于成员的返回类型。
下面的示例阐释了协变类型参数。 此示例定义了两个类型:Base 具有一个名为 PrintBases 的静态方法,该方法采用 IEnumerable<Base>(在 Visual Basic 中为 IEnumerable(Of Base))并输出元素。 Derived 继承自 Base。 此示例创建一个空 List<Derived>(在 Visual Basic 中为 List(Of Derived)),并且说明可以将该类型传递给 PrintBases 且在不进行强制转换的情况下将该类型分配给类型 IEnumerable<Base> 的变量。 List<T> 实现 IEnumerable<T>,它具有一个协变类型参数。 协变类型参数是可使用 IEnumerable<Derived> 的实例而非 IEnumerable<Base> 的原因。
<span style="color:#2a2a2a;">namespace ConsoleApplication1{ class Program { abstract class Shape { public virtual double Area { get { return 0; } } } class Circle : Shape { private double r; public Circle(double radius) { r = radius; } public double Radius { get { return r; } } public override double Area { get { return Math.PI * r * r; } } } class ShapeAreaComparer : System.Collections.Generic.</span><span style="color:#ff0000;">IComparer</span><span style="color:#2a2a2a;"><Shape> { int IComparer<Shape>.Compare(Shape a, Shape b) { if (a == null) return b == null ? 0 : -1; return b == null ? 1 : a.Area.CompareTo(b.Area); } } static void Main(string[] args) { SortedSet<Circle> circlesByArea = new SortedSet<Circle>(new ShapeAreaComparer()) { new Circle(7.2), new Circle(100), null, new Circle(.01) }; foreach (Circle c in circlesByArea) { Console.WriteLine(c == null ? "null" : "Circle with area " + c.Area); } Console.Read(); } }}</span>
从 .NET Framework 4 开始,某些泛型接口具有逆变类型参数;例如:IComparer<T>、IComparable<T> 和 IEqualityComparer<T>。 由于这些接口只具有逆变类型参数,因此这些类型参数只用作接口成员中的参数类型。
下面的示例阐释了逆变类型参数。 该示例定义具有 Area 属性的抽象(在 Visual Basic 中为 MustInherit)Shape 类。 该示例还定义一个实现IComparer<Shape>(在 Visual Basic 中为 IComparer(Of Shape))的 ShapeAreaComparer 类。 IComparer<T>.Compare 方法的实现基于 Area 属性的值,所以 ShapeAreaComparer 可用于按区域对 Shape 对象排序。
Circle 类继承 Shape 并重写 Area。 该示例创建 Circle 对象的 SortedSet<T>,使用采用 IComparer<Circle>(在 Visual Basic 中为 IComparer(Of Circle))的构造函数。 但是,该对象不传递 IComparer<Circle>,而是传递一个用于实现 IComparer<Shape> 的 ShapeAreaComparer 对象。 当代码需要派生程度较大的类型的比较器 (Circle) 时,该示例可以传递派生程度较小的类型的比较器 (Shape),因为 IComparer<T> 泛型接口的类型参数是逆变参数。
向 SortedSet<Circle> 中添加新 Circle 对象时,每次将新元素与现有元素进行比较时,都会调用 ShapeAreaComparer 对象的 IComparer<Shape>.Compare方法(在 Visual Basic 中为 IComparer(Of Shape).Compare 方法)。 方法 (Shape) 的参数类型比被传递的类型 (Circle) 的派生程度小,所以调用是类型安全的。 逆变使 ShapeAreaComparer 可以对派生自 Shape 的任意单个类型的集合以及混合类型的集合排序。
- 协变和逆变
- 协变和逆变
- 协变和逆变
- 协变和逆变
- C# 4 协变和逆变
- 委托中的协变和逆变
- c# 委托 协变和逆变
- scala中的协变和逆变
- C# 中的协变和逆变
- 什么是协变和逆变
- C# 协变和逆变
- Java协变和逆变
- 第六节:协变和逆变
- Scala之协变和逆变
- 协变和逆变之疑问
- C# 协变和逆变
- C#的协变和逆变
- C# 协变和逆变
- spring里的标注 @Service @Autowired
- 希望删除一些下载的记录
- 阶段一:2014/8/06 strchr
- hdu-1862-EXCEL排序
- 拓扑排序
- 协变和逆变
- ios addressbook
- spring 配置 java mail 发送邮件
- 无线路由:关于WDS,Repeater等模式的说明
- Java中静态方法是否属于线程安全
- mybatis传入混合参数(多个不同类型的参数)
- 百度地图 helloword
- Python 正则表达式对名字格式的转换
- 设置EditPlus的默认编码方式