在編程語言中,“協變”是指能夠使用與原始指定的派生類型相比,派生程度 更大的類型。“逆變”則是指能夠使用派生程度更小的類型。在 .NET Framework 4 和 Visual Studio 2010 中,C# 和 Visual Basic 都支持在泛型接口和委托中 使用協變和逆變,並允許隱式轉換泛型類型參數。
如果泛型接口或委托的泛型參數聲明為協變或逆變,則將該泛型接口或委托稱 為“變體”。C# 和 Visual Basic 都允許您創建自己的變體接口和委托。在匹配 方法簽名和委托類型方面,非泛型委托也支持協變和逆變。這樣,您不僅可以為 委托指派具有匹配簽名的方法,而且可以指派這樣的方法:它們返回與委托類型 指定的派生類型相比,派生程度更大的類型(協變),或者接受相比之下,派生 程度更小的類型的參數(逆變)。
實例
首先定義一個接口IColor及兩個派生類
public interface IColor { }
public class Red : IColor { }
public class Blue : IColor { }
定義ColorDemo類用來寫展示協變與逆變的邏輯
public class ColorDemo{}
編寫具體實現
public class ColorDemo
{
//協變委托
private delegate T CovarianceDelegate<out T> ();
//逆變委托
private delegate void ContravarianceDelegate<in T>(T color);
private static string colorInfo;
public void CoreMethod()
{
//協變
CovarianceDelegate<IColor> a1 = ColorMethod;
a1.Invoke();
CovarianceDelegate<Red> a2 = RedMethod;
a2.Invoke();
a1 = a2;
a1.Invoke();
//逆變
ContravarianceDelegate<Blue> b1 = BlueMethod;
b1.Invoke(new Blue());
ContravarianceDelegate<IColor> b2 = ColorMethod;
b2.Invoke(new Red());
b1 = b2;
b1.Invoke(new Blue());
}
private void Invoke(dynamic invokeObj)
{
Console.WriteLine("invokeObj類型為:" + invokeObj.GetType().Name);
invokeObj.Invoke();
}
private IColor ColorMethod()
{
colorInfo = "無色";
Console.WriteLine(colorInfo);
return null;
}
private void ColorMethod(IColor color)
{
colorInfo = "無色";
Console.WriteLine(colorInfo);
}
private Red RedMethod()
{
colorInfo = "紅色";
Console.WriteLine(colorInfo);
return new Red();
}
private void BlueMethod(Blue blue)
{
colorInfo = "藍色";
Console.WriteLine(colorInfo);
}
}
運行結果
static void Main(string[] args)
{
ColorDemo colorDemo =new ColorDemo();
colorDemo.CoreMethod();
Console.ReadLine();
}