Variance in delegates

C# supports variance in delegate types with matching method signatures. This feature was introduced in .NET Framework 3.5. This means delegates can now be assigned with matching signatures but also that methods can return derived types.

If a method has a return type derived from the one defined in a delegate, it is defined as covariance in delegates. Similarly, if a method has fewer derived parameter types than those defined in a delegate, it is defined as contravariance.

Let's look at an example to understand covariance. For the purpose of this example, we will create a few classes.

Here, we will create the ParentReturnClass, Child1ReturnClass, and Child2Return classes. Each of these has a string type property. Both child classes are inherited from ParentReturnClass:

internal class ParentReturnClass
{
public string Message { get; set; }
}

internal class Child1ReturnClass : ParentReturnClass
{
public string ChildMessage1 { get; set; }
}
internal class Child2ReturnClass : ParentReturnClass
{
public string ChildMessage2 { get; set; }
}

Now, let's add two new methods to the previously defined helper class, each returning the respective child classes we defined earlier:

public Child1ReturnClass ChildMehod1() 
{
return new Child1ReturnClass
{
ChildMessage1 = "ChildMessage1"
};
}
public Child2ReturnClass ChildMehod2()
{
return new Child2ReturnClass
{
ChildMessage2 = "ChildMessage2"
};
}

Now, we will define a delegate that returns ParentReturnClass. We'll also define a new method that will initiate this delegate for each of the child methods. One important point to observe in the following code is that we have used explicit typecast to convert ParentReturnClass into ChildReturnClass1 and ChildReturnClass2:

delegate ParentReturnClass covrianceDelegate();
public void CoVarianceSample()
{
covrianceDelegate cdel;
cdel = new HelperClass().ChildMehod1;
Child1ReturnClass CR1 = (Child1ReturnClass)cdel();
Console.WriteLine(CR1.ChildMessage1);
cdel = new HelperClass().ChildMehod2;
Child2ReturnClass CR2 = (Child2ReturnClass)cdel();
Console.WriteLine(CR2.ChildMessage2);
}


//Output:
ChildMessage1
ChildMessage2

In the preceding example, the delegate is returning ParentReturnClass. However, both ChildMethod1 and ChildMethod2 are returning child classes that were inherited from ParentReturnClass. This means that methods that return more derived types than those defined in the delegate are permitted. This is called covariance.

Now, let's look at another example to understand contravariance. Extend the previously created helper class by adding a new method that accepts ParentReturnClass as a parameter and returns void:

public void Method1(ParentReturnClass parentVariable1) 
{
Console.WriteLine(((Child1ReturnClass)parentVariable1).ChildMessage1);
}

Define a delegate that accepts Child1ReturnClass as a parameter:

delegate void contravrianceDelegate(Child1ReturnClass variable1);

Now, create a method to initiate the delegate:

public void ContraVarianceSample()
{
Child1ReturnClass CR1 = new Child1ReturnClass() { ChildMessage1 = "ChildMessage1" };
contravrianceDelegate cdel = new HelperClass().Method1;
cdel(CR1);

}

//Output:
ChildMessage1

Because method one works with the parent class, it will definitely work with the class that is inherited from the parent class. C# permits fewer derived types as parameters than those defined in the delegate.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.62.94