Friday 19 October 2018

C# - IEnumerable++ Our First Linq Query

So I want to start running some Linq queries against our simple classes which support IEnumerable (and thus IEnumerator). I want to start poking around at the types that are created on our behalf by LINQ expressions.

So following on from the code in previous post where I built two classes Customers, and Orders to poke around how to implement IEnumerable (even though I ended up delegating to IList<>), I can now write a LINQ query, so here is the console program's Main() method

    class Program
    {
        static void Main(string[] args)
        {
            Customers custs = new Customers();
            var query = from Customer c in custs where c.Country != "Mexico" select new { c.CustomerId, c.CustomerName };

            foreach (var customer in query)
            {
                Console.WriteLine(customer.GetType().ToString());
                Console.WriteLine(customer);
            }
        }
    }

So this compiles but let's inspect what is compiled on our behalf, here is a screenshot of the query variable

The screenshot is not copy and pastable so I give in plain text what I see because I want to Google on these terms ...

query        {Sytem.Linq.Enumerable.WhereSelectEnumerableIterator<ConsoleEnumTut01.Customer, <>f_AnonymousType0<int,string> >

query, Non-Public members
current      { CustomerId = 1, CustomerName = "Big Corp" }
enumerator   {ConsoleEnumTut01.Customers}
predicate    {Method = { Boolean <Main> b__0_0(ConsoleEnumTut01.Customer)}}
selector     {Method = {<>f__AnonymousType0`2[System.Int32,System.String] <Main>b__0_1(ConsoleEnumTut01.Customer)}}
source       {ConsoleEnumTut01.Customers}

Above, in the Non-Public members <Main> refers to the method Main(), if you move the code to a separate procedure called, e.g. Foo(), then the <Main> will change to <Foo>. Also, we can see the select new clause is compiled to an anonymous type though I cannot says what the 0`2 suffix naming convention represents. Lastly, one can see b__0_0 and b__0_1 looks like it is incrementing; if moved to a separate method Foo() then they become b__1_0 and b__1_1 so I'm guessing the increments are there to avoid some name class in some name space somewhere. Lots to investigate there.

Why delve to such a low level? Well, I'm interested to see if we actually need these Linq expressions or if they can be compiled separately from strings etc. and be parameterized. Dynamic Linq does this though I am (as yet) unclear as to how far I can take this.

No comments:

Post a Comment