Here's an instance where if you remove the contravariance in
marker it won't 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 contrived, sure, but should at least give you an idea of the kind of things you can't do without it.
Especially think in terms of if AddLabelClickCallback
and AddButtonClickCallback
were library functions and Callback
was a library delegate. If it was defined without contravariance, you'd have to define different delegates showButtonText
and showLabelText
even though you just want them to do the same thing.