I’ve run into a number of cases where people have built LINQ providers and only tested them with C# clients. In one case, I was sitting next to the person who wrote the provider when we discovered that using a VB client didn’t work with their provider because they failed to test it.
I’ve even seen it in the sample Entity Framework provider available on the MSDN Code Gallery when parsing the .Include() method. Hopefully, you will be able to access my VB translation of the EF sample provider once it finishes going through the legal hoops.
So, why are these providers failing when run against a different language? Much of LINQ is based around language syntactic sugar. The various compiler teams added different optimizations when translating your LINQ code into real framework code. (Update: the VB Team explained the difference in a blog post from 2 years ago.) Let’s take a look at a simple case which tripped up at least two providers I tested recently. The query in question is perhaps the most common query when looking at LINQ samples:
From c In Customers _ Where c.City = "London" _ Select c
This seems to be a very straight forward example. Let’s take a look at what the compiler translates is query into.
Customers.Where (c => (c.City == "London"))
Customers.Where (Function(c) => (Operators.CompareString (c.City, "London", False) == 0)) .Select ((Function(c) => c)
Notice here that the C# code does a literal translation into an equality operator. However, the VB team uses what turns out to be a slightly faster CompareString operator implementation. This doesn’t seem like too much of an issue until you consider the differences that this causes in the Expression tree that you need to parse in your provider. Using the Expression Tree Visualizer, you can see how much of a difference these two expressions cause under the covers. In this case, the C# version is on the left and VB is on the right.
Notice that both versions start with the same constant expression and the right expression constant of the Binary Expression is the same in both cases. However, the remainder of the expression is different between the two source examples.
The moral of the story: If creating a framework or API which will be consumed by multiple languages, make sure to include tests in each of those languages.