C# variance : The Co and Contra variance explained

by silvercrux @ 9. August 2010 23:07

This topic can be ideally explained with a simple and pragmatic 2 part Q and A.

What is Covariance and Contra variance in C# 4 ?

This can be best explained by an example. If you image there are 2 types : x and y, then exactly one of the statement is true :

1) x < y
2) x > y
3) x = y
4) x not related to y (Both are totally different having their own chain)

Memory locations in C# all have a type associated with them. At runtime you can store an object which is an instance of an equal or smaller type in that memory location.

So considering that :
Covariant : Is converting from narrower to a wider type
contra variant : Is Conversion from wider to a narrower type

Covariance basically means that the return value of a method that is referenced by your delegate can have a different return type than that specified by the delegate itself, so long as the return type of the method is a subclass of the return type of the delegate. Basically this means from going to a wider type from a narrower type.

 

Why do you care about Co and Contra variance ?

Prior to C# 4.0, language was not capable of working with co and contra variance conversion. Now it does support. So the question is why you might need them ? Well the answer is simple, now Inheritance hierarchy works across Generic types, thanks to Covariance and Contra variance support in C# 4.0.

Let's take an example (This would not work in versions prior to C# 4.0) :

Covariant

   1: class Fruit { }
   2:     class Apple : Fruit { } 
   3:  
   4:     class Program
   5:     {
   6:         delegate T MyFunc<out T>();
   7:         static void Main(string[] args)
   8:         {
   9:              MyFunc<Apple> apple1 = () => new Apple();
  10:              MyFunc<Fruit> fruit = apple1;
  11:         }
  12:     } 
  13:  

In the above code we are assigning a narrower type to a wider type. Notice the use of the word "out" in Delegate MyFunc definition

Contravariant

   1: class Fruit { }
   2:     class Apple : Fruit { } 
   3:  
   4:     class Program
   5:     {
   6:         delegate void MyAction<in T>(T a);
   7:         static void Main(string[] args)
   8:         {
   9:              MyFunc<Fruit> fruit = () => new Fruit();
  10:              MyFunc<Apple> apple1 = fruit;
  11:         }
  12:     }

In the above code we are assigning a narrower type to a wider type. Notice the use of the word "in" in Delegate MyFunc definition

I hope this clears the confusion about Co and Contra-variance. If it's still not clear we can talk via comments :)





C# 4.0 Named Parameters Explained

by silvercrux @ 9. August 2010 22:18

Prior to C# 4.0, we have to remember (though intellisense helped!) the order of each argument to use it in the consuming code.

C# 4.0 introduces a new concept which frees you to provide value to arguments in a specified order. For example, a function that calculates dearness allowance for an employee can be called in the standard way by sending arguments for salary and inflation percentage by position, in the order defined by the function.

   1: GetDearnessAllowance(5000, 9);


If you do not remember the order of the parameters but you do know their names, you can send the arguments in either order, weight first or height first.

   1: GetDearnessAllowance(wage: 5000, inflation: 9);

 

OR

   1: GetDearnessAllowance(inflation: 9, wage: 5000);

Named arguments also improve the readability of your code by identifying what each argument represents.

A named argument can follow positional arguments, as shown here.

   1: GetDearnessAllowance(5000, inflation: 9);

However, a positional argument cannot follow a named argument. The following statement causes a compiler error.

   1: //GetDearnessAllowance(weight: 5000, 9);

 

We hope this clears up the matter.





C# 4.0 Optional Parameters Explained

by silvercrux @ 21. May 2010 00:00

With release of the C# 4, the gap of features between VB.NET and C# just became narrower. C# 4.0 has introduced a new “Optional Parameters” support. So instead of explicitly passing in value for each variable in a method/constructor you can rely on default value defined in the method signature.

Let’s take a simple example :

 

public void AddPerson(string Name,int Age=30)
{
...
}

In this Example, now under C# 4.0, you can call this method as

 

AddPerson("Joe") //Age will implicitly be 30

 

Though theoretically this looks a nice shortcut, practical use of this may be discouraged. Adding an optional parameter to a public method that’s called from an external assembly requires recompilation of both assemblies – just as if the parameters were mandatory. This is so because this is just a syntactic sugar coat by the C# compiler. Behind the scenes C# compiler inserts code equivalent to AddPerson(“Joe”,30).

It is for this very reason optional parameters should be avoided in public methods that are supposedly going to be used by External assemblies.





C# 101: Virtual Function Members Vs Abstract Function Members

by silvercrux @ 12. March 2010 12:13

This series is going to be a C# refresher that reminds you of C# features you sometimes forget.

A function can be marked as virtual when you don’t want your sub-classes to compulsorily provide implementation of some specialized form. So you can treat virtual as opposite of abstract, where you have to compulsorily provide implementation.

Consider this small fragment :

   1: public abstract class Person
   2: {
   3:     public abstract string Name {get;}
   4:     public virtual decimal TotalDebts
   5:     {
   6:         get
   7:         {
   8:             return 0;
   9:         }
  10:     }
  11: }
  12:  
  13: public class RichPerson : Person
  14: {
  15:     public override string Name 
  16:     {
  17:         get {return "I am Rich";}
  18:     }
  19: }
  20:  
  21: public class PoorPerson : Person
  22: {
  23:     public override string Name 
  24:     {
  25:         get {return "I am just a Poor guy";}
  26:     }
  27:     
  28:     public override decimal TotalDebts
  29:     {
  30:         get{return 1000000;}
  31:     }
  32: }

In this example the property “Name” declared in Line 3 is abstract while property “TotalDebts” in Line 4 is virtual.  The difference is while it is compulsory for deriving class to override “Name”, it is optional for deriving class to override “TotalDebts”. In this particular case PoorPerson is under heavy debt and implements TotalDebts to return his TotalDebts.





© Copyright SilverCrux Technologies. All rights reserved. We provide website html services.