java泛型逆变与协变-用于泛型中修饰泛型字母的接口和泛型委托能使用
发布时间:2023-06-11 22:15 浏览次数:次 作者:佚名
用于 泛型中修饰泛型字母的,只有泛型接口和泛型委托能使用!!!
协变:out
和谐的变化 , 自然的变化,因为里氏替换原则父类可以装子类,所以子类变父类
逆变:in
逆常规的变化 , 不正常的变化,因为里氏替换原则父类可以装子类但是子类不能装父类,所以父类变子类
完整代码:
using System;
namespace Test
{
//1.返回值和参数
//2.用out修饰的泛型,只能作为返回值
delegate T TestOut<out T>();
//delegate T TestOut(T t);// 不能作为参数
//3.用 in 修饰的泛型只能作为参数
delegate void TestIn<in T>(T t);
//delegate T TestIn(T t);// 不能作为返回值
//4.只有泛型接口和泛型委托能使用
//class Test//错误
//{
//
//}
//5.结合里氏替换原则理解
class Father
{}
class Son:Father
{}
class Program
{
public static void Main(string[] args)
{
//协变
TestOut<Son> os = ()=>
{
return new Son();
};
TestOut<Father> of = os;//协变就是父类泛型委托装载子类泛型委托
//如果delegate T TestOut();没有out则无法转换,实际返回的是os里的函数返回值为Son
//逆变
TestIn<Father> inf = (value)=>
{
};
TestIn<Son> ins =inf;//逆变就是子类泛型委托装载父类泛型委托
//如果delegate void TestIn(T t);没有in则无法转换,实际返回的是inf里的函数参数为Father value
Console.ReadKey();
}
}
}
协变(covariant)和逆变(contravariant)是指在继承关系中子类的类型如何与父类的类型进行比较。
协变指的是子类可以转换为更通用的父类,即子类的类型参数是父类类型参数的子类型。例如java泛型逆变与协变,一个返回IEnumerable类型的方法可以返回IEnumerable类型,因为string类型是object类型的子类型。在C#中协变用out关键字表示java泛型逆变与协变,只能用于接口和委托的类型参数。
逆变指的是子类可以转换为更特定的父类,即子类的类型参数是父类类型参数的父类型。例如,一个接受IComparer类型参数的方法可以接受IComparer类型,因为object类型是string类型的父类型。在C#中逆变用in关键字表示,只能用于委托的类型参数。
// 协变示例
IEnumerable<string> strings = new List<string>();
IEnumerable<object> objects = strings; // 可以进行协变
// 逆变示例
Comparison<object> comparison = (object1, object2) => 0;
Comparison<string> stringComparison = comparison; // 可以进行逆变
需要注意的是,虽然协变和逆变可以方便地处理一些类似转换的问题,但它们也会导致一些安全隐患和类型不匹配的错误,因此需要仔细考虑使用场景和实际需求。