Dealing with iterations over null lists in LINQ to Objects

Problem

If you used LINQ to Objects you have certainly come across iterations over null values resulting in an ArgumentNullException being thrown at you.

See this example:

int[] b = null;
var query = from i in b select i;

In the case above the error is obvious but if the list comes as an argument of a method or some more complicated way it is hard to spot it. Sure, the obvious solution is an easy one. A simple if statement before will do it:

if (b != null)
    var query = from i in b select i;

What about nested loops? Like this

class Tubo
{
public List<string> Strings;
}
...
IList<Tubo> tubos = ...;
var query = from t in tubos
from s in t.Strings
select s;

Sure, we could add guardian clauses like the if before:

if (tubos != null)
     var query = from t in tubos
        where t.Strings != null
        from s in t.Strings
        select s;

The problem with this approach is that it gets cluttered and it complicates the flow, specially the first if.

Solution

So, here is my proposal and I am sure it has been proposed before (I just couldn’t find it on Google, err, I mean internet).

public static class Extension
{
public static IList<T> Safe<T>(this IList<T> source)
{
if (source == null)
return new T[0];
else return source;
}
}

The extension method makes sure that query always gets a non-null list by making an empty one if it is null. The trick with extension method is that they can be invoked on null values which are passed as this argument.

And the last nested LINQ to Objects loop would look like:

var query = from t in tubos.Safe()
             from s in t.Strings.Safe()
             select s;

I am not sure that the extension method name Safe is adequate or not but it sure does help in code readability.

What do you say?

A better call to Control.Invoke

Whenever one needs to interact with WinForms UI from within another thread (the one that didn't create the UI controls) one has to rely on the Control.Invoke (or BeginInvoke/EndInvoke pair) method. Otherwise one gets an InvalidOperationException exception with message “Cross-thread operation not valid: Control ‘name here’ accessed from a thread other than the thread it was created on”. This happens because WinForms (and .net framework in general) isn’t thread safe.

Let’s say I want to know how many controls are on the form. I’d do it like this (Form f holds the instance of the Form created in some thread):

public static int GetControlsCount(Form f)
{
if (f.InvokeRequired)
return (int)f.Invoke(new Func<Form, int>(GetControlsCount), f);
else
return f.Controls.Count;
}
...
int count = GetControlsCount(f);

This way the method GetControlsCount is thread safe. That’s fine. But what should I do if I require to access many methods in such a thread safe way (I’ll blog about the reason I need it in a future post)? Creating this kind of wrapper for every different method I need to call would be kind of boring at best and difficult to maintain, don’t you think?

So I created a generic method instead, like this:

public static TRet InvokeSync<TRet>(Control control, Func<TRet> func)
{
if (control.InvokeRequired)
return (TRet)control.Invoke(func);
else
return func();
}
...
int count = InvokeSync<int>(f, () => f.Controls.Count);

This is much better because I don’t need to create a wrapper for each method – instead I merely provide a delegate (of type Func<int> in my case). There are two drawbacks to this approach.

1. It won’t work with different number of parameters nor it will work with methods (= actions) that don’t return a value. The only workaround is to create various similar methods that accepts different argument number and return either a result or no result (void). Here is a bunch of such variations:

public static void InvokeSync(Control control, Action action)
{
if (control.InvokeRequired)
control.Invoke(action);
else
action();
}
public static void InvokeSync<T>(Control control, Action<T> action, T argument)
{
if (control.InvokeRequired)
control.Invoke(action, argument);
else
action(argument);
}
public static TRet InvokeSync<T, TRet>(Control control, Func<T, TRet> func, T argument)
{
if (control.InvokeRequired)
return (TRet)control.Invoke(func, argument);
else
return func(argument);
}
public static TRet InvokeSync<T1, T2, TRet>(Control control, Func<T1, T2, TRet> func, T1 argument1, T2 argument2)
{
if (control.InvokeRequired)
return (TRet)control.Invoke(func, argument1, argument2);
else
return func(argument1, argument2);
}

2. Passing Control parameter (which is required to do the synchronization) is such pre .net 3.5-ish. Instead extensions methods can be used, like this:

public static class Extender
{
public static TRet InvokeSync<TRet>(this Control c, Func<TRet> func)
{
if (c.InvokeRequired)
return (TRet)c.Invoke(func);
else
return func();
}

public static void InvokeSync(this Control c, Action func)
{
if (c.InvokeRequired)
c.Invoke(func);
else
func();
}
}

So the final version of the call to InvokeSync looks even nicer:

int count = f.InvokeSync<int>(() => f.Controls.Count);

That’s it.

InvokeSyncExtender.zip (572.00 bytes)