Recently, while parsing the code of one program, I noticed a method that looked like this:
public void Foo<T>( IEnumerable <T> items)
{
if (items == null || items.Count() == 0)
{
//
}
}
The method takes a generic transfer and checks if it is empty. Do you see a potential problem here? I will hint the problem in this line:
')
items.Count () == 0
And what is the problem here? The problem is that this line can be very inefficient.
If you call our method, passing it an enumeration that does not implement
ICollection <T> (for example,
IQueryable result of a query to the Entity Framework or LINQ to SQL), the
Count () method will iterate over the entire collection in order to perform this check.
In the case where the enum implements the
ICollection <T> , everything is in order. The
Count () method is optimized for such cases and will check the
Count property .
Speaking in human language, our line answers the question β
Is the number in the listing equal to zero? ". But this is not what interests us. In fact, we need to answer the question β
Does the listing have at least one element? ".
If we approach the problem in this way, the solution will become obvious: use the
Any extension from the
System.Linq namespace.
public void Foo<T>( IEnumerable <T> items)
{
if (items == null || !items.Any())
{
//
}
}
The beauty of this method is that it only needs to call the
IENumerable interface's
MoveNext only once! You can have an infinitely large enumeration, but
Any will return the result immediately.
It would be even better, since such a check is used constantly, to think about the implementation of its simple extension method:
public static bool IsNullOrEmpty<T>( this IEnumerable <T> items)
{
return items == null || !items.Any();
}
Now, with this method, the source code looks even simpler:
public void Foo<T>( IEnumerable <T> items)
{
if (items.IsNullOrEmpty())
{
//
}
}
With this extension method in your toolkit, you will never check the enumeration void again inefficiently.