.Net 4.5 intro­duced a handy lit­tle new method Comparer<T>.Create to aid the cre­ation of bespoke com­par­ers, which is great because it means that you don’t have to define a new Com­parer class when it is going to be needed once.

In case you’re won­der­ing, it’s still not pos­si­ble to define anony­mous imple­men­ta­tion of inter­faces in C#, but with Comparer<T>.Create you can at least cre­ate a bespoke instance of IComparer<T> from an anony­mous method:

As a side, you can also apply the same tech­nique for other sin­gle method inter­faces your­self, for instance, if you were happy to ignore the exis­tence of the Zip exten­sion method for the sake of the exam­ple, you could define your own Zip exten­sion method which takes in an instance of an IZipper<T, U, V>:

Whilst we’re on the topic of anony­mous inter­face imple­men­ta­tion. F# has a nice lit­tle fea­ture call Object Expres­sions, it pro­vides a mech­a­nism for cre­at­ing anony­mous types that are based on exist­ing base type, inter­face, or set of inter­faces, and for the two exam­ples, here’s how that solu­tion might look in F#:

Notice that there’s no need for an explicit imple­men­ta­tion class for IZipper<T, U, V> inter­face at all using Object Expres­sions and how much less code you end up writ­ing with F#! So seri­ously, why aren’t you check­ing out F# already!? Winking smile

Share

Sup­pose you have an array of num­bers, say, [1, 3, 5, 7, 9, …], and you want to pair each ele­ment up with its neigh­bour in the array, e.g. [[1, 3], [3, 5], [5, 7], [7, 9], …].

Sure, you can iter­ate through the indices of the ele­ments and recur­sively grab the ele­ment at an index and its neighbour:

   1: // an array of odd numbers

   2: var arr = new[] { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 };

   3:  

   4: // standard imperative way, iterate through the indices and grab

   5: // the elements from the arrays

   6: var arrPairs = new List<int[]>();

   7: for (var i = 0; i < arr.Length - 1; i++)

   8: {

   9:     arrPairs.Add(new[] { arr[i], arr[i+1] });

  10: }

OR, you can use LINQ and the Zip method added in .Net 4 and do this instead:

   1: var arrPairsLinq = arr.Skip(1).Zip(arr, (second, first) => new[] { first, second }).ToArray();

A much more ele­gant solu­tion, no? ;-)

Share

Admit it, we’ve all done it before, writ­ing those nasty nested loops just so we can iter­ate through mul­ti­ple lists to get some combination/permutation of the lists, e.g.:

   1: for (int i = 0; i < 10; i++)

   2: {

   3:     for (int j = 0; j < 10; j++)

   4:     {

   5:         for (int k = 0; k < 10; k++)

   6:         {

   7:             // do something

   8:         }

   9:     }

  10: }

This code obvi­ously works and well under­stood amongst devel­op­ers, but it’s not very read­able and try­ing to ter­mi­nate the outer loops from the inner loops is a pain and requires you to use one or more boolean flags which you need to track on every iter­a­tion at poten­tially every level of your loop…

A bet­ter way to solve this com­mon prob­lem is to use LINQ to ‘flat­ten’ the nested loops into a sin­gle loop:

   1: var triplets = from I in Enumerable.Range(0, 10)

   2:                from J in Enumerable.Range(0, 10)

   3:                from K in Enumerable.Range(0, 10)

   4:                select new { I, J, K };

   5:  

   6: foreach (var triplet in triplets)

   7: {

   8:     // do something

   9: }

Sweet, right? :-)

Share

I saw an inter­est­ing use of covari­ance today, con­sider an inter­face IMy­Class and an imple­ment­ing class MyClass:

   1: public interface IMyClass { }

   2:

   3: public class MyClass : IMyClass { }

If you want to con­vert an List<MyClass> to a List<IMyClass> you would nor­mally use the Enumerable.Cast method but did you know that you can also use C# 4’s sup­port for covari­ance in the type para­me­ter and do this instead:

   1: var original = new List<MyClass>();

   2:

   3: var converted = original.ToList<IMyClass>()

Funky, eh? ;-)

Though I think it’s a party trick best avoided for any pro­duc­tion code, for which you should still prefer:

   1: var converted = original.Cast<IMyClass>().ToList();

because:-

  • it achieves the same result
  • it is just as expressive
  • it is the stan­dard way of doing this kind of con­ver­sions in LINQ
  • it is under­stood by most C# devel­op­ers so unlikely to cause confusion

There’s another argu­ment for using Cast, in the case of use-defined implicit/explicit oper­a­tors. Imag­ine if you have another class which does not inherit from MyClass but defines an explicit oper­a­tor which allows you to cast an instance of MyClass:

   1: public class MyOtherClass

   2: {

   3:     public static explicit operator MyClass(MyOtherClass other)

   4:     {

   5:         return new MyClass();

   6:     }

   7: }

In cases like this, you won’t be able to use the covari­ance trick:

   1: void Main()

   2: {

   3:     var original = new List<MyClass>();

   4:

   5:     Console.WriteLine(original.GetType());                               // List<MyClass>

   6:

   7:     // cast here doesn't actually do anything

   8:     Console.WriteLine(original.Cast<IMyClass>().ToList().GetType());     // List<IMyClass>

   9:

  10:     // changes the compile type, works because of covariance

  11:     Console.WriteLine(original.ToList<IMyClass>().GetType());            // List<IMyClass>

  12:

  13:     // casts the objs to MyOtherClass using the defined convertor

  14:     Console.WriteLine(original.Cast<MyOtherClass>().ToList().GetType()); // List<MyOtherClass>

  15:

  16:     // this line won't compile.

  17:     // it doesn't work because this is not covariance, there's no inheritance

  18:     // relationship between MyClass and MyOtherClass

  19:     // Console.WriteLine(objs.ToList<MyOtherClass>().GetType());

  20: }

Ref­er­ences:

Stack­Over­flow ques­tion – Cast­ing List<T> – covariance/contravariance problem

Share

Look­ing at these two images snapped right off MSDN, what do you notice?

image

image

.

.

.

that IEnumerable<T> extends IEnu­mer­able but IList<T> doesn’t extend IList!?

I know, pecu­liar isn’t it?

 

Turns out, it was for a good reason:

“A sequence of inte­gers can be treated as a sequence of objects, by box­ing every inte­ger as it comes out of the sequence. But a read-write list of inte­gers can­not be treated as a read-write list of objects, because you can put a string into a read-write list of objects. An IList<T> is not required to ful­fill the whole con­tract of IList, so it does not inherit from it.”

Inter­est­ing.

Share