委托的逆变和协变
1.4.1 概念
协变和逆变来源于类型和类型之间的绑定,C#4.0开始在泛型的接口和委托上支持协变和逆变,不过在这个版本之前的委托也是支持协变和逆变的。
如果有类型Parent和其子类Sub,那么Parent p=new Sub();这种的类型转换是安全的。如果有一种类型和Parent类型进行了绑定,比如说Parent[]数组,如果Sub[]到Parent[]的转换是安全的,我们就说是协变,如果相反的方向上转换是安全的,我们就说是逆变了。
C#的协变和逆变没有完整的阐述这个数学和物理上的概念,C#为协变和逆变的实现捆绑了很多条件:
①必须是泛型的委托或接口
②协变只能支持返回类型
③逆变只能支持参数
而这些条件总归是实现了一个面向对象原则:里氏替换原则。也就是说,不管是协变还是逆变,最终都是一种类型安全的转换,没有不安全的转换发生。
// 协变 :和谐的变化
// 下面这个定义可以说明协变,在定义object 基类型的地方,可以传入string 派生类型的实例。
object[] myArray = new string[] { “abc”, “def”, “ghi”, // 。.. };
// 逆变:不正常的变化 指从派生类到基类的变化
// 数组不支持逆变性,我们以泛型接口描述
// in 是C# 关键字,表示泛型参数类型支持逆变
interface IContravariant《in A》 { } // 一个支持逆变的泛型接口
interface IExtContravariant《in A》 : IContravariant《A》 { }// 派生接口
class Sample《A》 : IContravariant《A》 { } // 基接口的实现
class Program
{
static void Test()
{
// 实例化object类型的 IContravariant 接口
IContravariant《Object》 iobj = new Sample《Object》();
// 实例化object类型的 IContravariant 接口
IContravariant《String》 istr = new Sample《String》();
// 下面这一句不会报错,因为泛型参数In 表示支持逆变,可以实现从特殊类型到基础类型的变化。
istr = iobj;
}
}
1.4.2 委托中的逆变和协变
• 在.Net framework 2.0之后的版本,委托支持对参数的逆变性和对返回值的协变性。
• 参数的逆变性:由于Action 的定义中,参数增加了对逆变的支持,所以 如果将Action 的委托赋值给Action
委托的逆变和协变
1.4.1 概念
协变和逆变来源于类型和类型之间的绑定,C#4.0开始在泛型的接口和委托上支持协变和逆变,不过在这个版本之前的委托也是支持协变和逆变的。
如果有类型Parent和其子类Sub,那么Parent p=new Sub();这种的类型转换是安全的。如果有一种类型和Parent类型进行了绑定,比如说Parent[]数组,如果Sub[]到Parent[]的转换是安全的,我们就说是协变,如果相反的方向上转换是安全的,我们就说是逆变了。
C#的协变和逆变没有完整的阐述这个数学和物理上的概念,C#为协变和逆变的实现捆绑了很多条件:
①必须是泛型的委托或接口
②协变只能支持返回类型
③逆变只能支持参数
而这些条件总归是实现了一个面向对象原则:里氏替换原则。也就是说,不管是协变还是逆变,最终都是一种类型安全的转换,没有不安全的转换发生。
// 协变 :和谐的变化
// 下面这个定义可以说明协变,在定义object 基类型的地方,可以传入string 派生类型的实例。
object[] myArray = new string[] { “abc”, “def”, “ghi”, // 。.. };
// 逆变:不正常的变化 指从派生类到基类的变化
// 数组不支持逆变性,我们以泛型接口描述
// in 是C# 关键字,表示泛型参数类型支持逆变
interface IContravariant《in A》 { } // 一个支持逆变的泛型接口
interface IExtContravariant《in A》 : IContravariant《A》 { }// 派生接口
class Sample《A》 : IContravariant《A》 { } // 基接口的实现
class Program
{
static void Test()
{
// 实例化object类型的 IContravariant 接口
IContravariant《Object》 iobj = new Sample《Object》();
// 实例化object类型的 IContravariant 接口
IContravariant《String》 istr = new Sample《String》();
// 下面这一句不会报错,因为泛型参数In 表示支持逆变,可以实现从特殊类型到基础类型的变化。
istr = iobj;
}
}
1.4.2 委托中的逆变和协变
• 在.Net framework 2.0之后的版本,委托支持对参数的逆变性和对返回值的协变性。
• 参数的逆变性:由于Action 的定义中,参数增加了对逆变的支持,所以 如果将Action 的委托赋值给Action
举报