泛型中的协变和逆变赋值






4.78/5 (4投票s)
只是一个快速示例,用于阐明我们可以做什么以及不能做什么
引言
与一些年轻的同事交流时,我意识到协变和逆变的概念往往没有完全被理解。
参考官方文档以获得正确的解释,本技巧仅旨在通过几行简单的代码示例来帮助理解这些概念。事实上,我记得我只有在开始阅读和编写相关代码后,才真正理解了这些概念。
如何操作泛型协变和逆变委托(和接口)
对于以下示例,我们只需要声明两个空类:Base
和 Derived
(其中 Derived
实现 Base
)。
class Base { }
class Derived : Base { }
我考虑了具有以下委托的赋值:
- 协变类型参数:
Func<out TResult>
- 逆变类型参数:
Action<in T>
- 同时具有协变和逆变类型参数:
Func<in T, out TResult>
请注意,所有示例都使用委托,但**对于接口来说是一样的**。
namespace Bagnasco.Samples.Variance
{
using System;
class Base { }
class Derived : Base { }
/// <summary>
/// Sample class just for clarifying variance concepts
/// (see: http://msdn.microsoft.com/it-it/library/dd799517(v=vs.110).aspx)
/// </summary>
class VarianceAssignmentsSample
{
public void VarianceSample()
{
Base baseInstance = new Base();
Derived derivedInstance = new Derived();
//Ok (ordinary polymorphism)
baseInstance = derivedInstance;
//Type parameters signature: <out TResult>
Func<Base> funcThatReturnsBase = () => baseInstance;
Func<Derived> funcThatReturnsDerived = () => derivedInstance;
//Ok, mutch like ordinary polymorphism (TResult is covariant)
funcThatReturnsBase = funcThatReturnsDerived;
//Not allowed (TResult is more derived in funcThatReturnsDerived and is not contravariant)
//funcThatReturnsDerived = funcThatReturnsBase;
//Type parameters signature: <in T>
Action<Base> actionThatTakesBase = _ => { };
Action<Derived> actionThatTakesDerived = _ => { };
//Ok (T is contravariant)
actionThatTakesDerived = actionThatTakesBase;
//Not allowed (T is not covariant and is less derived in actionThatTakesBase)
//actionThatTakesBase = actionThatTakesDerived
//Type parameters signature: <in T, out TResult>
Func<Base, Base> functionThatTakesBaseAndReturnsBase = _ => baseInstance;
Func<Base, Derived> functionThatTakesBaseAndReturnsDerived = _ => derivedInstance;
Func<Derived, Base> functionThatTakesDerivedAndReturnsBase = _ => baseInstance;
Func<Derived, Derived> functionThatTakesDerivedAndReturnsDerived = _ => derivedInstance;
//Ok (TResult is covariant and in functionThatTakesBaseAndReturnsBase is less derived)
functionThatTakesBaseAndReturnsBase = functionThatTakesBaseAndReturnsDerived;
//Not allowed
//(T is not covariant and in functionThatTakesBaseAndReturnsBase is less derived)
//functionThatTakesBaseAndReturnsBase = functionThatTakesDerivedAndReturnsBase;
//functionThatTakesBaseAndReturnsBase = functionThatTakesDerivedAndReturnsDerived;
//Not allowed
//(TResult is covariant and in functionThatTakesBaseAndReturnsDerived is more derived)
//functionThatTakesBaseAndReturnsDerived = functionThatTakesBaseAndReturnsBase;
//Not allowed
//(T is contravariant and in functionThatTakesBaseAndReturnsDerived is less derived
//functionThatTakesBaseAndReturnsDerived = functionThatTakesDerivedAndReturnsDerived;
//Not allowed
//(T is contravariant and in functionThatTakesBaseAndReturnsDerived is less derived,
// TResult is covariant and in functionThatTakesBaseAndReturnsDerived is more derived)
//functionThatTakesBaseAndReturnsDerived = functionThatTakesDerivedAndReturnsBase;
//All assignments are allowed
//(T is contravariant and in functionThatTakesDerivedAndReturnsBase is more derived,
// TResult is covariant and in functionThatTakesDerivedAndReturnsBase is less derived)
functionThatTakesDerivedAndReturnsBase = functionThatTakesBaseAndReturnsBase;
functionThatTakesDerivedAndReturnsBase = functionThatTakesBaseAndReturnsDerived;
functionThatTakesDerivedAndReturnsBase = functionThatTakesDerivedAndReturnsDerived;
//Ok (T is contravariant and in functionThatTakesDerivedAndReturnsDerived is more derived)
functionThatTakesDerivedAndReturnsDerived = functionThatTakesBaseAndReturnsDerived;
//Not allowed
//(TResult is covariant and in functionThatTakesDerivedAndReturnsDerived is more derived)
//functionThatTakesDerivedAndReturnsDerived = functionThatTakesBaseAndReturnsBase;
//functionThatTakesDerivedAndReturnsDerived = functionThatTakesDerivedAndReturnsBase;
}
}
}
希望这能帮助更好地理解泛型中的协变和逆变。