>LINQ Operators – Part X

>

I have been busy with a series of tasks and couldn’t find time to complete operators section. Although I had a safari account via university subscription and could read it online, I ordered a great book "C# 3.0 in a nutshell – O’Reilly – Joseph Albahari & Ben Albahari". Amazon estimate was I would get it sometime after August 11th but to my surprise I got it yesterday and maybe that has motivated me to spare extra time and write today’s (well tonight’s) blog. That is not the first book I read about C# and possibly won’t be the last but I must admit I liked it very much.

Conversion operators:

OfType: Returns the items from a sequence that are of a given type. This is especially useful with object collections where the collection can have multiple different types and ArrayList is a typical sample.  

ArrayList al = new ArrayList();
al.Add(5);
al.Add(7);
al.Add("Jim");
al.Add("Frank");
al.AddRange( Customers.Where( c => c.Country == "USA" ).ToList());

al.OfType<int>().Dump("Integers");
al.OfType<string>().Dump("Strings");
al.OfType<Customers>().Dump("Customers");

and here is the partial output in LinqPad:

OfType

With generic lists it is unlikely that you would need OfType.

Cast: Cast returns a sequence attempting to cast each member to a given type. If it can’t cast one ten it throws an error.  The difference between OfType and Cast is that, Cast throws an error if it encounters an incompatible type for casting. OfType, on the other hand, ignores incompatible types and simply returns an empty sequence if it cannot cast any member.

ArrayList al = new ArrayList();
al.Add(5);
al.Add(7);
al.Cast<int>().Dump("Integers");
al.OfType<string>().Dump("Strings");

Cast

If we try the OfType<string>() with Cast<string>() we will get an exception. Probably, Cast was added to support ArrayList and I can’t think of a good usage for it.

AsEnumerable: Upcasts a sequence to an IEnumerable sequence. Converting to an Enumerable effectively makes the sequence local and then you can apply methods that are not supported on a remote (IQueryable) source. For example Linq To SQL doesn’t support Last() but you could make the sequence local with AsEnumerable() and apply Last(). This nice sample is borrowed from LinqPad samples:

Regex wordCounter = new Regex (@"\b(\w|[-‘])+\b");

// Click the ‘SQL’ tab below after running this query - 
// notice that only the topic filtering
// predicate executes on SQL Server.

var query = MedicalArticles
           .Where (article => article.Topic == "influenza")
           .AsEnumerable()
           .Where (article => wordCounter.Matches (article.Abstract).Count < 100);

query.Dump();

 

The sample is getting medical articles whose topic is "influenza" and abstract is less than 100 words. Getting articles whose topic is "influenza" is trivial and the part before AsEnumerable() does that. That part is converted to this SQL:

— Region Parameters
Declare @p0 VarChar(9) Set @p0 = ‘influenza’
— EndRegion
Select [t0].[ID], [t0].[Topic], [t0].[Abstract]
  FROM [MedicalArticles] As [t0]
  WHERE [t0].[Topic] = @p0

The tricky part is counting the words. To count words regular expression is used and that wouldn’t execute on Linq To SQL. Applying AsEnumerable() converts the sequence to a local one and makes it possible to count the words using regular expression. 

AsQueryable: Converts a sequence to an IQueryable either by downcasting or by creating an IQueryable wrapper.  Converted to an IQueryable you can execute the query locally or remotely.

 ToArray and ToList: Convert a sequence to an array or generic list respectively. The generated array or list is a snapshot taken at the moment the query is run. That is particularly useful when a query needs to be executed often and a snapshot is sufficient.

ToDictionary and ToLookup: These operators create a snapshot dictionary of a given sequence. A dictionary is a key, element pair and you can access a member using the key as a indexer. ToDictionary creates a dictionary where sequence has  a unique entry per key (typically a primary key as in a table). ToLookup on the hand looks like foreign key and there can be multiple values for the same key in a sequence. The key is used as an indexer in both.

var cusDict = Customers.ToDictionary( c => c.CustomerID, c => c );
cusDict["BONAP"].Dump();

gives this result (note how we use the unique CustomerID as a key and the particular value to "BONAP" to access a member in dictionary via indexer):

ToDictionary

var clookup = Orders.ToLookup( o => o.CustomerID, o => o);

clookup["BONAP"].Dump("Orders of customer BONAP");

yields:

ToLookup

Other operators:

SequenceEqual: Also accepted as a quantifier operator this operator compares two sequences and returns true if the sequences have identical elements and in the same order.

var s1 = "ClintEastwood".ToLower().OrderBy(l => l);
var s2 = "OldWestAction".ToLower().OrderBy(l => l);
s1.SequenceEqual(s2).Dump("An anagram from wikipedia");

 

This concludes the standard Linq operators. There are other extension methods that are not yet available in .Net 3.5 and since it is extensible we should expect more in the future. Happy LINQinq.

Advertisements

About cetinbasoz

A developer working primarily with C#,F#,VFP,SQL server, Silverlight,Linq ...
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s