了解委托逆变有用性
本文关键字:有用性 了解 | 更新日期: 2023-09-27 18:31:03
所以我有一个委托定义为:
public delegate void MyDelegate<T>(T myParameter);
Resharper建议我应该按如下方式进行逆变T
:
public delegate void MyDelegate<in T>(T myParameter);
现在,我很难理解这有什么好处?我知道这会阻止我T
返回类型,但除此之外,通过使T
逆变,我得到了哪些有用的约束?也就是说,当需要将委托与实例一起使用时,我可以使用哪些实例创建
public delegate void MyDelegate<T>(T myParameter);
我无法创建的
public delegate void MyDelegate<in T>(T myParameter);
下面是一个实例,如果您删除逆变in
标记,它将无法编译:
delegate void Callback<in T>(T t);
public Form1()
{
InitializeComponent();
Callback<Control> showText = control => MessageBox.Show(control.Text);
var button = new Button();
AddButtonClickCallback(button, showText);
var label = new Label();
AddLabelClickCallback(label, showText);
}
static void AddButtonClickCallback(Button button, Callback<Button> callback)
{
button.Click += delegate { callback(button); };
}
static void AddLabelClickCallback(Label label, Callback<Label> callback)
{
label.Click += delegate { callback(label); };
}
当然,这有点做作,但至少应该让你了解没有它就无法做的事情。
特别是考虑AddLabelClickCallback
和AddButtonClickCallback
是库功能,Callback
是图书馆代表。 如果定义它没有逆变,则必须定义不同的委托showButtonText
和showLabelText
,即使您只是希望它们做同样的事情。
型上的 in
关键字允许进行隐式转换。基本上,您可以将较少的派生委托类型分配给委托...并不总是有用,请阅读此处以获取更多信息。
http://msdn.microsoft.com/en-us/library/dd469484.aspx
示例,来自 MSDN 文章:
// Contravariant delegate.
public delegate void DContravariant<in A>(A argument);
// Methods that match the delegate signature.
public static void SampleControl(Control control)
{ }
public static void SampleButton(Button button)
{ }
public void Test()
{
// Instantiating the delegates with the methods.
DContravariant<Control> dControl = SampleControl;
DContravariant<Button> dButton = SampleButton;
// You can assign dControl to dButton
// because the DContravariant delegate is contravariant.
dButton = dControl;
// Invoke the delegate.
dButton(new Button());
}
在该示例中,Control
将隐式转换为Button
类型,但如果未在 Button
类中定义到Button
类型的隐式转换以允许Control
成为Button
,则可能会发生异常。
详细了解隐式转换定义:http://msdn.microsoft.com/en-us/library/z5z9kes2.aspx
这在stackoverflow上被问了很多次:编程语言中的协方差和逆变
我建议你通过:http://blogs.msdn.com/b/ericlippert/archive/2007/10/22/covariance-and-contravariance-in-c-part-four-real-delegate-variance.aspx
Covariance and Contravariance in C#, Part One
Covariance and Contravariance in C#, Part Two: Array Covariance
Covariance and Contravariance in C#, Part Three: Method Group Conversion Variance
Covariance and Contravariance in C#, Part Four: Real Delegate Variance
Covariance and Contravariance In C#, Part Five: Higher Order Functions Hurt My Brain
Covariance and Contravariance in C#, Part Six: Interface Variance
Covariance and Contravariance in C# Part Seven: Why Do We Need A Syntax At All?
Covariance and Contravariance in C#, Part Eight: Syntax Options
Covariance and Contravariance in C#, Part Nine: Breaking Changes
Covariance and Contravariance in C#, Part Ten: Dealing With Ambiguity