CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 13 of 13
  1. #1
    Join Date
    Aug 2006
    Posts
    134

    Inconsistent exception behavior in FirstOrDefault() method with lambda expressiion

    Greetings!

    I am working with the following code in MS Visual Studio 2008:

    Code:
    SimpleADONetField foundField = null;
    foundField = fieldList.FirstOrDefault(field => field.m_name == checkedNode.Text);
    if (foundField == null)
    {
    	SimpleADONetField tagField = (SimpleADONetField)checkedNode.Tag;
    	fieldList.Add(tagField);
    }
    The first time this code is executed, the fieldList object exists but it is empty.

    When I step through this code, it behaves as I expect. Since fieldList is empty, nothing can match the condition, and foundField is set to null, which is the default value for reference types. But if I run my application through the VS debugger without stopping in this code, it throws a null reference exception, complaining that the field object is null when I try to read its m_name property.

    Why do I get an exception when running the code without stopping and not get an exception when stepping through it? Which behavior is correct? I can of course check to see if the list is empty before I run this code, but I don't think I should have to do that.

    Thank you very much.

    RobR

  2. #2
    Join Date
    Jan 2007
    Posts
    491

    Re: Inconsistent exception behavior in FirstOrDefault() method with lambda expressiio

    This exception is probably thrown because fieldList contains a null element, i.e., one of the elements of fieldList is null. Therefore, when the program runs your lambda expression on this element, it attempts to access the "m_name" field of a null pointer, causing a NullPointerException.

    Therefore, you should find out why the fieldList may have null elements. If when placing breakpoints, it never happens (maybe a different thread which updates the elements of fieldList causes this?), use other debug methods, such as logging.

    Tal.

  3. #3
    Join Date
    Aug 2006
    Posts
    134

    Re: Inconsistent exception behavior in FirstOrDefault() method with lambda expressiio

    Tal,

    Thank you for your reply. In one case, the collection did indeed contain an element whose value was null. I'm not sure why that happened, but of course it would explain the exception. I almost posted a reply to my own message saying that the problem was my fault when I saw that.

    But then I realized that the exception is also thrown when the collection contains zero elements. That is a perfectly normal case, and I think it should be handled by some method less traumatic than throwing an exception. I would like to understand that case more completely.

    RobR

  4. #4
    Join Date
    Jan 2007
    Posts
    491

    Re: Inconsistent exception behavior in FirstOrDefault() method with lambda expressiio

    What do you mean by "zero elements"?

  5. #5
    Join Date
    Aug 2006
    Posts
    134

    Re: Inconsistent exception behavior in FirstOrDefault() method with lambda expressiio

    I mean that the list is empty. The List<Field> object had been created, but no Field objects had ever been added to the list. The List<Field> object's Count property is zero.

    RobR

  6. #6
    Join Date
    Jan 2007
    Posts
    491

    Re: Inconsistent exception behavior in FirstOrDefault() method with lambda expressiio

    In that case, FirstOrDefault should return a value of null, and not exception should be thrown.
    Maybe the NullPointerException occurs after the FirstOrDefault call, when attempting to access some fields of the null pointer returned by FirstOrDefault?

  7. #7
    Join Date
    Aug 2006
    Posts
    134

    Re: Inconsistent exception behavior in FirstOrDefault() method with lambda expressiio

    I think Richardson's Second Law of Computational Unpredictability comes into play here: the word "should" has no meaning.

    I'll have to put together a tiny test program that I can paste here.

    RobR

  8. #8
    Join Date
    Jan 2010
    Posts
    1,133

    Re: Inconsistent exception behavior in FirstOrDefault() method with lambda expressiio

    Didn't test it myself, but, I think I have a decent idea of what's going on.
    Essentially, the lambda expression is pretty much just an anonymous method, that get's run via a delegate, at some point, inside the FirstOrDefault(Func<TSource, Boolean> predicate) extension method.
    The documentation says that this method "returns the first element of the sequence that satisfies a condition or a default value if no such element is found".
    Unfortunately, it doesn't explicitly specify what the method does if the collection is not null, but it has zero elements, or null elements, or elements with null fields.

    So, it's understandable that you would assume that it would behave similarly to the parameterless FirstOrDefault() extension method, which returns a default value for empty collections. But, that's not so easy.

    OK: Two cases to consider.
    If the collection was empty, the FirstOrDefault(predicate) extension method could simply return a default value, and never invoke the lambda. Apparently, they didn't think of that in Microsoft. No biggie: you can check the size yourself, prior to the call.

    Here's the more problematic case, though. If the collection is not empty, then the lambda needs to access some of the fields of the current element, in order to perform some test. In doing so, it can try to access and/or modify a null reference, just like any other method could.
    In that case, throwing an exception is perfectly suitable.
    I guess Microsoft wanted to treat both cases the same way - but they should have documented it better.

    You can use some of IL decompiling tools to check the actual implementation.
    Last edited by TheGreatCthulhu; May 8th, 2012 at 09:06 PM.

  9. #9
    Join Date
    Jan 2009
    Posts
    596

    Re: Inconsistent exception behavior in FirstOrDefault() method with lambda expressiio

    Quote Originally Posted by TheGreatCthulhu View Post
    Here's the more problematic case, though. If the collection is not empty, then the lambda needs to access some of the fields of the current element, in order to perform some test. In doing so, it can try to access and/or modify a null reference, just like any other method could.
    I've not used this stuff myself, but wouldn't a simple null check in the lambda fix this case:
    Code:
    foundField = fieldList.FirstOrDefault(field => (field != null) && (field.m_name == checkedNode.Text) );
    ?

  10. #10
    Join Date
    Jan 2010
    Posts
    1,133

    Re: Inconsistent exception behavior in FirstOrDefault() method with lambda expressiio

    Yes, but that's in the client code, the code that uses the FirstOrDefault method.
    I was talking about the implementation of FirstOrDefault, and about why would it throw an exception in certain scenarios - it's developers could not predict what lambda expression will get passed in.

    BTW, I used ILSpy to look inside.
    I said that people at MS maybe wanted to treat both of my cases the same, but the method actually does return default(TSource) if the collection is empty. Here:
    Code:
    // System.Linq.Enumerable
    public static TSource FirstOrDefault<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
    {
    	if (source == null)
    	{
    		throw Error.ArgumentNull("source");
    	}
    	if (predicate == null)
    	{
    		throw Error.ArgumentNull("predicate");
    	}
    	TSource result;
    	foreach (TSource current in source)     // <-- foreach body never runs for empty collections
    	{
    		if (predicate(current))
    		{
    			result = current;
    			return result;
    		}
    	}
    	return default(TSource);
    	return result;                   // <-- this is because of some bug in ILSpy
    }
    So, there is something strange going on here. Why would the debugger complain?
    Last edited by TheGreatCthulhu; May 9th, 2012 at 09:09 AM.

  11. #11
    Join Date
    Aug 2006
    Posts
    134

    Re: Inconsistent exception behavior in FirstOrDefault() method with lambda expressiio

    Hmmm... It seems there is something else going on in the program that first seemed to show me this problem. In this code:

    Code:
    		private void button1_Click(object sender, EventArgs e)
    		{
    			List<SomeClass> list = new List<SomeClass>();
    			try
    			{
    				SomeClass something = list.FirstOrDefault(value => value.m_value < 10);
    				MessageBox.Show("No exception thrown.");
    			}
    			catch (Exception ex)
    			{
    				MessageBox.Show(ex.Message);
    			}
    		}
    I get the message box saying "No exception thrown."

    Thanks for all your thoughts!

    RobR

  12. #12
    Join Date
    Jan 2010
    Posts
    1,133

    Re: Inconsistent exception behavior in FirstOrDefault() method with lambda expressiio

    OK, I just stumbled upon something that has me confused. There are 3 kinds of FirstOrDefault extension methods:
    • System.Linq.Enumerable.FirstOrDefault - the one I posted
    • System.Linq.ParallelEnumerable.FirstOrDefault - which I would need to inspect more thoroughly before I can say more, and
    • System.Linq.Queryable.FirstOrDefault - which is the one that has me confused, a and is given below


    Code:
    // System.Linq.Queryable
    public static TSource FirstOrDefault<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate)
    {    
    	if (source == null)
    	{
    		throw Error.ArgumentNull("source");
    	}
    	if (predicate == null)
    	{
    		throw Error.ArgumentNull("predicate");
    	}
        
        return source.Provider.Execute<TSource>(      // simply executes expression trees which return a single value
            Expression.Call(                        // represents a method call
                null, 
                ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(   // takes the type argument and replaces the generic param
                    new Type[]
                    {
                        typeof(TSource)         // Results in: FirstOrDefault<TSource> - this method.
                    }
                ), 
                new Expression[]
                {
                    source.Expression,                      // 1st parameter: the collection, or rather, the query
                    Expression.Quote(predicate)             // 2nd parameter: the predicate. Quote: an expression that has a constant value of type Expression - basically, a lambda.
                }
            )
        );
    }
    I don't get it; as far as I can tell, this method, in a very convoluted way, ends up calling itself?! I must have made a mistake in my interpretation somewhere.
    Anyone out there with more experience with expression trees, who can shed some light on this?
    Last edited by TheGreatCthulhu; May 9th, 2012 at 10:12 AM.

  13. #13
    Join Date
    Jan 2010
    Posts
    1,133

    Re: Inconsistent exception behavior in FirstOrDefault() method with lambda expressiio

    @OP: Any multithreading involved?

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured