Code Renaissance is about building great teams and great software. By exploring best practices, team interactions, design, testing and related skills Code Renaissance strives to help you create the team and codebase that you've always wanted.

Extending LINQ to Objects

To start off there seems to be a fair bit of confusion about what LINQ is because a lot of related technologies fall under that name. Here's a short list of Linq Technologies:

  • Linq Query Expressions - A declarative syntax similar to SQL. At compile time the standard query operators in the query expression get mapped to method calls.
  • Linq Providers a.k.a. Linq to [whatever] - whether it be SQL, XML, or custom providers these are data providers that work with Linq Query Expressions. 
  • Linq to SQL Mapping (Not to be confused with the Linq to SQL Provider) -  Microsoft created these specialized mapping tools for SQL Server though as you may have heard they will not be available going forward. Microsoft is dropping them in favor of the Entity Framework.
  • Linq Extension Methods - Each Linq Provider comes with a library of extension methods. Some of them match up to standard query operators and others have to be called using method syntax.

What I'll be covering is adding extension methods LINQ to Objects so that when you include the "System.Linq" namespace your new methods automatically get included. Any methods that are added should be in line with the other extension methods and should be carefully chosen; it would be very easy to clutter the namespace.

In the application I'm working on I need to check lists of objects for duplicates; if a duplicate is found then the list is rejected. Adding an efficient hasDuplicates method to the Linq namespace seems like a good option. Here's the code:

using System.Collections.Generic;

namespace System.Linq
{

 public static class DuplicateExtension{

  public static bool HasDuplicates(this IList list, Func areEqual)
  {
   for (int index1 = 0, lastIndex = list.Count() - 1; index1 < lastIndex; index1++)
   {
    for (int index2 = index1 + 1; index2 <= lastIndex; index2++)
    {
     if (areEqual(list[index1], list[index2]))
     {
      return true;
     }
    }
   }
   return false;
  }

  public static bool HasDuplicates(this IEnumerable list, Func areEqual)
  {
   for (int index1 = 0, lastIndex = list.Count() - 1; index1 < lastIndex; index1++)
   {
    for (int index2 = index1 + 1; index2 <= lastIndex; index2++)
    {
     if (areEqual(list.ElementAt(index1), list.ElementAt(index2)))
     {
      return true;
     }
    }
   }
   return false;
  }

 }

}

I created an extension method first for IList, which is what I needed, then copied it over and made some modifications for IEnumerable (since in general Linq to Objects methods support IEnumerable). Neither of these have been tested yet for efficiency and I suspect the IEnumerable one in particular can be improved upon.

Other than that everything is pretty straight forward. All I did is create extension methods in the Linq namespace. The first parameter (preceded by 'this') indicated the interface to be extended and the namespace was the namespace to be extended, in this case System.Linq. The static class name is not referenced when calling the extension method so it can be named anything you like. I guess the most surprising thing about digging into this was finding out there wasn't more to it.

The extension method above is very flexible and can be called as follows:

var dupicateFound = list.HasDuplicates((a,b)=> a.ToLower() == b.ToLower()

Given a list of items of type T then you pass in a method compare two objects of type T to determine if they are matched/duplicate. Here I'm passing in a lambda expression that takes two parameters of type T and returns a bool. In this simple example the signature is Func<string, string, bool> though you can work with lists of any object type and pass in a method that uses any sort of match logic you like.

0 - What do you think?: