C#中协变抗变之我见


      在.NET4.0中,新加入了协变与抗变的内容,最近查了一下MSDN,对它有了一个大概的理解,希望能够帮助到和我一样的菜鸟。

      协变:

      协变非常类似于普通的多态性的分配,它是针对成员的返回值类型,定义时使用关键字out,假定您有一个名为 Base 的基类和一个名为 Derived 的派生类:

      IEnumerable<Derived> d = new List<Derived>();
      IEnumerable<Base> b = d;

      这就是一个简单的协变的应用,它主要是从派生类到基类的一个转化。

      抗变(逆变):

      抗变主要是在传递类型参数的时候使用的,定义时使用关键字in,这样做有利于保证参数传递的安全性和效率。还是上边的例子:
     IDisplay<Base> bd=new ShapeDisplay();
     IDisplay<Derived> dd=bd;

     这是一个简单的抗变的例子,它主要是从基类到派生类的转换。

    下边是一个协变抗变综合在一块的例子:

using System;
using System.Collections;
using System.Collections.Generic;
namespace xiebian
{
	public class Shape
	{
		public double Width{get;set;}
		public double Height{get;set;}
		public override string ToString()
		{
			return String.Format("Width:{0}, Height:{1}",Width,Height);
		}
	}
	public class Rectangle:Shape
	{
	}
	public interface IIndex<out T>
	{
		T this[int index]{get;}
		int Count{get;}
	}
	public class RectangleCollection:IIndex<Rectangle>
	{
		private Rectangle[] data=new Rectangle[3]
		{
			new Rectangle{Height=1,Width=5},
			new Rectangle{Height=2,Width=6},
			new Rectangle{Height=5,Width=7}
		};
		public static RectangleCollection GetRectangles()
		{
			return new RectangleCollection();
		}
		public Rectangle this[int index]
		{
			get
			{
				if(index<0||index>data.Length)
					throw new ArgumentOutOfRangeException("index");
				return data[index];
			}
		}
		public int Count
		{
			get
			{
				return data.Length;
			}
		}
		
	}
	public interface IDisplay<in T>
	{
		void Show(T item);
	}
	public class ShapeDisplay:IDisplay<Shape>
	{
		public void Show(Shape s)
		{
			Console.WriteLine("{0} Width:{1} ,Height:{2}",s.GetType().Name,s.Width,s.Height);
		}
	}
	class Program
	{
		public static void Main()
		{
			IIndex<Rectangle> rectangles=RectangleCollection.GetRectangles();
			IIndex<Shape> shapes=rectangles;			
			//这里用的是协变,它是针对成员的返回值类型,从派生类到基类的转换。
			for(int i=0;i<shapes.Count;i++)
				Console.WriteLine(shapes[i]);
			IDisplay<Shape> shapedisplay=new ShapeDisplay();
			IDisplay<Rectangle> rectangledisplay=shapedisplay;
			//这里用的是抗变,它是针对传递的参数类型,从基类到派生类的转换。
			//当然,前提是保证程序能够正常的运行,即:IDisplay(Shape s)not IDisplay(Rectangle s)(需要的是基类即可完成的任务)
			rectangledisplay.Show(rectangles[0]);
		}
	}
}

 结果:

 

 

 

 

 

 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值