Friday, April 20, 2007 12:02 PM bart

C# 3.0 Quiz - Core LINQ concepts

All C# quizzes on my blog so far were covering C# 2.0 language features. Today, we'll start with a first quiz on C# 3.0, which is rather a knowledge check than a quiz in the classic sense of the word. This quiz focuses on the core concepts in C# 3.0 that drive LINQ.

Consider the code fragment below:

Defect piece of LINQ code - Copy Code
1 // 2 // Put additional namespace imports here 3 // 4 5 class Program 6 { 7 static void Main() 8 { 9 Source<Customer> src = null; 10 var res = from s in src 11 orderby s.Name, s.Age descending 12 where s.Name == "Bart" 13 select s.Age; 14 } 15 } 16 17 class Customer 18 { 19 public string Name { get; set; } 20 public int Age { get; set; } 21 } 22 23 abstract class Source<T> 24 { 25 // 26 // Put code here 27 // 28 }

This piece of code doesn't compile with the following messages:

Error 1 The type arguments for method 'System.Linq.Queryable.OrderBy<TSource,TKey>(System.Linq.IQueryable<TSource>, System.Linq.Expressions.Expression<System.Linq.Func<TSource,TKey>>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

The goal of this quiz is to provide a minimal abstract definition of the Source<T> class in order to make the code compile. We won't execute the application though, we're just focusing on the compilation (and the result of the compilation).

A few rules:

  • You're only allowed to put abstract method signatures in regions marked by comments.
  • You shouldn't implement any interface (after all, the previous rule doesn't allow touching line 23).
  • Any method you add to Source<T> should return an object of the generic type Source`1.

Additional questions:

  1. Two different (categories of) solutions for implementation of Source<T> exist, explain.
  2. Will these two solutions mentioned in question 1 produce different IL code for Program::Mail? If so, explain why and point out the differences.
  3. How many different minimal solutions exist (renaming a parameter doesn't count for a different solution of course)?

Have fun!

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Filed under: ,

Comments

# re: C# 3.0 Quiz - Core LINQ concepts

Monday, April 23, 2007 2:39 AM by Alex Thissen

Hi Bart,

Since nobody seems to answering here's my take on it:

One minimal implementation:

abstract class Source<T>

{

 public abstract Source<T> OrderBy(Func<T, string> sorter);

 public abstract Source<T> ThenByDescending(Func<T, int> sorter);

 public abstract Source<T> Select(Func<T, int> selector);

 public abstract Source<T> Where(Func<T, bool> predicate);

}

There are indeed two categories of solutions for this problem. The implementation above uses Func<A,B> type delegates as arguments in the OrderBy, ThenByDescending, Select and Where methods. Another category is where no Func<A,B> would be used, but Expression<Func<A,B>>. The compiler would behave differently for each of the two categories. For Func<A,B> it would emit real IL for lambda expressions passed as arguments for a call to one of the methods. In the case of <Expression<Func<A,B>> that would be a constructed expression tree. So, yes the produced IL (question 2) would be different.

The last one is the trickiest. The total number of minimal solutions would be made from the permutations of the options per method. The options per method are:

Func or Expression<Func<>>

Using generic type T or hardcoded Customer

That's four options per method and four methods total, so 4^4 = 256 minimal solutions (since the choice per method has no influence on the rest of the methods).

There would be even more if there were BCL classes that had a Name and Age property of type string and int. The compiler can never really tell what actual type was meant in the first parameter for Func and Expression<Func>, apart from the Name and Age properties that should exist on the type. It will be happy with any correct signature for the methods, as long as it's unambiguous.

I hope I got it all worked out right. Keep up the good work. This was definitely the right question to ask for a deeper understanding of Linq.

And congrats on your job at Microsoft.

# re: C# 3.0 Quiz - Core LINQ concepts

Monday, April 23, 2007 1:13 PM by Ming Chen

Alex, your post is very informative, thanks!

It turns out the compiler is smart enough to optimize away the call the Select if it doesn't perform any real functionality. So Select need not be part of the the minimum set of functions...

# re: C# 3.0 Quiz - Core LINQ concepts

Thursday, April 26, 2007 6:50 AM by Alex Thissen

Hi Ming,

You're absolutely right. Select would not be a part of the minimum functions. I figured that with the projection from Customer to its Age property the Select is necessary in this case. Of course, only because of the rules by Bart (no changes elsewhere in the code).

Alex

# Answers to C# 3.0 Quiz - Core LINQ concepts

Monday, April 30, 2007 11:29 AM by B# .NET Blog

This post covers the answers to the C# 3.0 - Core Linq concepts questions. Alex and Ming provided a set

# Community Convergence XXVI

Sunday, May 06, 2007 6:42 PM by Charlie Calvert's Community Blog

The biggest news in the C# community is the official announcement of Silverlight at the MIX conference.

# An explanation of Linq query providers

Thursday, March 20, 2008 1:46 PM by Alex Thissen Weblog Build 1.15.10.1971

Linq query providers appear all over the place. Some say &quot;Linq to Everything&quot; to refer to all

# An explanation of Linq query providers | Alex Thissen Weblog Build 1.15.10.1971

Pingback from  An explanation of Linq query providers | Alex Thissen Weblog Build 1.15.10.1971