详解C# 协变和逆变
什么是协变和逆变
C#中的协变和逆变都是关于类型转换的扩展,它们开启了更多利用类型层次结构优化代码的可能性。
协变
协变是指派生类对象可以赋值给基类对象的一种类型转换,即如果有A是B的子类,那么IEnumerable<A>
可以被隐式转换成IEnumerable<B>
。这里的IEnumerable<A>
就是协变的例子。在C# 4.0及之后的版本中使用关键字out
,来表示协变的类型参数。
示例:
class Person { }
class Student : Person { }
IEnumerable<Student> stuList = new List<Student>();
IEnumerable<Person> pList = stuList; // 协变
上面的例子中,IEnumerable<Student>
是IEnumerable<Person>
的子类,因此可以被隐式地转换。
逆变
逆变是指基类对象可以赋值给派生类对象的一种类型转换,即如果有B是A的基类,那么Action<B>
可以被隐式转换成Action<A>
。这里的Action<T>
就是逆变的例子。在C# 4.0及之后的版本中使用关键字in
来表示逆变的类型参数。
示例:
class Person { }
class Student : Person { }
Action<Person> hp = p => Console.WriteLine("Hello " + p.GetType().Name);
Action<Student> hs = hp; // 逆变
上面的例子中,Action<Person>
是Action<Student>
的基类,因此可以被隐式地转换。
在委托中的应用
由于C#中委托是一种类型,因此它们也可以支持协变和逆变。在使用协变和逆变的委托时,需要使用Func
和Action
泛型委托类型,它们内部指定参数类型和返回值类型可以是协变或逆变的。
示例:
class Person { }
class Student : Person { }
Func<Student, string> getFullName = s => s.GetType().Name;
Func<Person, string> getFullNameForPerson = getFullName; // 协变
Action<Person> hp = p => Console.WriteLine("Hello " + p.GetType().Name);
Action<Student> hs = hp; // 逆变
总结
协变和逆变扩展了C#中类型转换的可能性,可以使代码变得更加灵活,同时也使代码更加简洁易懂。在实际的开发过程中,应该根据具体的场景灵活地使用协变和逆变。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解c# 协变和逆变 - Python技术站