Friday, December 21, 2007

Liking LINQ: A Question of Efficacy

Consider these two equivalent blocks of code.  First, the LINQ way:

foreach(var assignable in (from Assembly a in BuildManager.GetReferencedAssemblies()
select a.GetTypes() into types
from t1 in types
where typeof(I).IsAssignableFrom(t1)
select t1))
Cache.AddType(assignable.Name, Cache.ContainsType(assignable.Name) ? DUPLICATE_TYPE : assignable);


And, the "normal way":



foreach (Assembly assembly in BuildManager.GetReferencedAssemblies())
foreach (Type type in assembly.GetTypes())
if (typeof(I).IsAssignableFrom(type))
{
if (!Cache.ContainsType(type.Name))
Cache.AddType(type.Name, type);
else
Cache.AddType(type.Name, DUPLICATE_TYPE);
}


I cannot rightly make a judgement call on which way is better.  They have the same result.  Though, it is safe to say that normal way should perform better.  It is also clear, oddly, that the normal way has fewer lines of meaningful code; thus, it is easier to grok.  So, what do you think?  If you had to maintain the code base, which one would you prefer.  FWIW, I'm going to go with the normal way.



This leaves me with the question of efficacy.  Certainly there are niches where LINQ is superior, or the only option, but for general object collection work, should we just ignore this language feature?  Perhaps when PLINQ comes available we'll have a good reason to use it.  Time will tell.

1 comment:

jef said...

perhaps a couple of alternatives:

var types =
from a in BuildManager.GetReferencedAssemblies()
t in a.GetTypes()
where typeof(I).IsAssignableFrom(t)
select t;

foreach( var type in types)
Cache.AddType(type.Name, Cache.ContainsType(type.Name)
? DUPLICATE_TYPE : type);

-----

foreach( var type in
BuildManager.GetReferencedAssemblies()
.SelectMany(a=>a.GetTypes()).Where(t=>typeof(I).IsAssignableFrom(t)))
{
Cache.AddType(type.Name, Cache.ContainsType(type.Name)
? DUPLICATE_TYPE : type);
}