Understanding the complementarity of delegates

So, I have a delegate defined as:

public delegate void MyDelegate<T>(T myParameter); 

Resharper suggests that I should make T contravariant as follows:

 public delegate void MyDelegate<in T>(T myParameter); 

Now it’s hard for me to understand why this is useful? I know that this is stopping me from making a T return type, but other than that, what other useful restrictions will I get by creating counterfeiting T ? That is, when it is time to use a delegate with an instance, which instances can I create using

 public delegate void MyDelegate<T>(T myParameter); 

which I cannot create with

 public delegate void MyDelegate<in T>(T myParameter); 
+8
generics c # delegates variance
source share
3 answers

Here's an instance in which if you remove the in contravariance marker in , it will not compile:

 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); }; } 

Somewhat far-fetched, of course, but should at least give you an idea of ​​what you cannot do without it.

It is especially important to understand that AddLabelClickCallback and AddButtonClickCallback were library functions, and Callback was a library delegate. If it were defined without contravariance, you would need to define different delegates to showButtonText and showLabelText , although you just want them to do the same.

+6
source share

The in keyword generally allows for implicit conversion. Basically, you can assign fewer delegated delegate types to your delegate ... Not always useful, read here for more information.

http://msdn.microsoft.com/en-us/library/dd469484.aspx

Example from an MSDN article:

 // 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()); } 

In this example, Control will be implicitly converted to a Button type, although an exception may occur if an implicit conversion to a Button type has not been defined in the Button class to allow Control to become a Button .

More on implicit conversion definitions: http://msdn.microsoft.com/en-us/library/z5z9kes2.aspx

+4
source share

This has been asked about stackoverflow many times: Covariance and contravariance in programming languages.

I suggest you go through: 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 
+1
source share

All Articles