Covariance versus Contravariance

Ok so I stumbled on to this subject the other day and thought it was worth noting. Take these simple classes:

public class First
{
  public String FirstOutput { get; set; }
}

public class Second : First
{
  public String SecondOutput { get; set; }
}

public class Third : Second
{
  public String ThirdOutput { get; set; }
}

So from this you can see that Third inherits Second which in turns inherits First. By terminology this would mean that Third is “smaller” than Second and First is “larger” than both. Here’s an example of Covariance:

public class Covariance
{
  public Covariance()
  {

      Func<First> returnFirstFunc = ReturnFirst;
      //This works since the Func has a return type of First

      Func<Second> returnSecondFunc = ReturnThird;
      Second secondTest = returnSecondFunc();
      secondTest.FirstOutput = "First";
      secondTest.SecondOutput = "First";
      //This works since the Func has a return type of Third which is smaller
       //that Second.  Therefore anyone using this Func will expect a Second to
       //be returned and will only use the methods/properties that a Second object
       //would have.  Methods/Properties that Third has by inheritance.

      Func<Third> returnThirdFunc = ReturnSecond;
      //THIS WILL NOT WORK
       //Due to Covariance, the return of the method must be equal or smaller
       //that the expected type.  returnThirdFunc expects a Third or smaller object
       //but the ReturnSecond method returns a Second which is not smaller than Third.
       //Afterall, Third : Second
       //
       //Third thirdTest = returnThirdFunc();
       //Is the same as:
       //Third thirdTest = new Second();
  }

  private First ReturnFirst()
  {
      return new First();
  }

  private Second ReturnSecond()
  {
      return new Second();
  }

  private Third ReturnThird()
  {
      return new Third();
  }
}

Basically what this all means is that with return types, the return type must be smaller or equal to the field it’s being set to. When you are dealing with Funcs, the return type must be smaller or equal to the return type for the method it’s being set it. Why is that? Well think of it like this:

It’s your first day on the job and some guy tells you to write something with whatever returnFirstFunc() returns. Now you have no way to look at the code, so you can only know that it returns First. For all you know, it could return First, Second, or Third. So you would do this:

First someFirst;

someFirst = returnFirstFunc();  //Could return anything smaller than First
someFirst.FirstOutput;  //Completely legal and safe

But would you do this?

someFirst.ThirdOutput;

Of course not since you only can assume it is a First. Now let’s do this in reverse. Say from the above example you were allowed to do this:

Func<Third> returnThirdFunc = ReturnSecond;

Could you do this?

Third third;

third = returnThirdFunc();
third.ThirdOutput;

Yeah you can’t since the Second type doesn’t have the ThirdOutput property.

In short Covariance is the allowance of Smaller types or equal. If a method returns back Third, then you can use that method for anything that is Third or Smaller (Second, First, Object) but not for something Larger (Fourth, Fifth, ect).

And then you hit the wall.

So as this dynamic nonsense continues, there is a sticking point to how much fun I can have. The wall? Anonymous types and generic declarations.

Here’s the old:

  Func<User, Int32> selectUserID = currentUser => currentUser.UserID;

Great if I want to select userIDs, but what if I want UserIDs AND UserNames… Easy right?

 userList.Select(currentUser => new { currentUser.ID, currentUser.UserName });

Now this is the old way, but I want the new way… IE the Func way. Problem is here

  Func<User, EHH??> selectUserID = currentUser =>  new { currentUser.ID, currentUser.UserName };

You see, there’s a problem. What the hell do I put at the return type? Fact is, without creating a method that passes back a Func or a class that has UserName and UserID properties, I’m screwed. Now from what I read here I think I get it. First take the func:

  Func<K, T>

I have K and T that the compiler has to figure out what they are. Well it’s safe to say in the example User is K, but what is T? Well it has to figure that out from the Lamdba expression. The lambda expression has no idea what it is because it’s an anonymous type. So why not just use var?

  Func<User, var>

Seems easy enough. I don’t have to know the type because of var right? Wellll problem is the compiler is looking at the lambda expression to figure out what var will be. Mr. Lambda expression can’t really figure out the type either. Enter the wall. Currently there is no way around this without methods or classes created. Supposedly there are things called Mumble Types on the way that will solve this problem.

I ain’t gettin’ paid enough for this…

Remember when I said I’m not exactly great with programming terms? Well if I didn’t, I am saying it now. So I saw the word “closures” today and had no idea what this was. All excited about something new, I found out that closures is just another word for anonymous methods, although it may include stuff outside that scope but I’m not sure. Anyhow, although this seemed to be yet another attack of the stupid I stumbled across something here. Basically what caught me is how value types are handled with Funcs. Take this method:

using System;
using System.Collections.Generic;
using System.Linq;

public static Func<Int32> ReturnIntegerWithinFuncReturningMethod(WhichMethod methodToReturn)
{
  Int32 integerToIncrement;
  Func<Int32> returnMethod;

  integerToIncrement = 0;
  returnMethod = null;

  switch(methodToReturn)
  {
  case WhichMethod.AddOne:
   returnMethod = new Func<Int32>(() => { return integerToIncrement += 1;} );
   break;
  case WhichMethod.AddTwo:
   returnMethod = new Func<Int32>(() => { return integerToIncrement += 2; });
   break;
}

 return returnMethod;
}

Let’s say we test it like this:

Func<Int32> returnedMethod;
Int32 integerToCheck;

returnedMethod = ReturnIntegerWithinFuncReturningMethod(WhichMethod.AddOne);
integerToCheck = returnedMethod();
Assert.IsTrue(integerToCheck == 1, "Actual value is:" + integerToCheck.ToString());

integerToCheck = returnedMethod();
Assert.IsTrue(integerToCheck == 2, "Actual value is:" + integerToCheck.ToString());

These both pass. How does that make sense? You would think that it would return 1 both times since from first glance integerToIncrement lives outside the actual Func that is returned. You would think from this that Int32 is a reference type. When a value type is “attached” to a Func like this one is, apparently it keeps a reference to it and therefore the original Int32 is updated every time the Func is called. Something to remember.