5

I am suffering a weird problem in C# 4.5.

I have this in my model:

private DataMatrix<T> _matrix;

public DataMatrix<T> Matrix
{
    get { return _matrix; }
    set { _matrix = value; }
}

And I have a property which uses this:

public object SingleElement
{
     get
     {
        if (Matrix == null) return String.Empty;

        if (Matrix.ColumnCount >= 1 && Matrix.RowCount >= 1)
        {
           return Matrix[0, 0];
        }
        return null;
     }
 }

When I run it, before calling SingleElement, the Matrix property is null. But it doesn't return String.Empty, it goes to the second if-statement.

That's my Immediate window says: Immediate window

I'm a bit confused. What did I do wrong?

6
  • 7
    Does Matrix have an overloaded == operator that fails to properly handle null? Commented May 13, 2014 at 11:05
  • 4
    Or perhaps it has an overridden ToString() method that returns "null"? Commented May 13, 2014 at 11:05
  • What makes you think Matrix is null ? I kinda suspect that it is non-null. Commented May 13, 2014 at 11:08
  • 1
    See also MSDN: Viewing Data in the Debugger. The Immediate Window isn't always the best choice. The easiest would be to hover the mouse over your Matrix variable. Commented May 13, 2014 at 11:10
  • 2
    @MarcGravell It indicates both things, which is the source of the OP's confusion. Either Matrix is null and == is incorrectly implemented, Matrix is not null and ToString() returns null for some reason or some third option we haven't considered yet. Commented May 13, 2014 at 11:13

1 Answer 1

5

This is a most likely a broken equality operator (==), which can be reproduced with the following code:

class Foo
{
    public static bool operator == (Foo x, Foo y)
    {
        return false; // probably more complex stuff here in the real code
    }
    public static bool operator != (Foo x, Foo y)
    {
        return !(x == y);
    }
    static void Main()
    {
        Foo obj = null;
        System.Diagnostics.Debugger.Break();
    }
    // note there are two compiler warnings here about GetHashCode/Equals;
    // I am ignoring those for brevity
}

now at the breakpoint in the immediate window:

?obj
null
?(obj==null)
false

Two fixes:

  • preferred would be to fix the operator, perhaps adding before anything else:

    if(ReferenceEquals(x,y)) return true;
    if((object)x == null || (object)y == null) return false;
    // the rest of the code...
    
  • alternative, if you can't edit that type, is to avoid using the operator; consider using ReferenceEquals explicitly in your code, or performing object-based null checks; for example:

    if(ReferenceEquals(Matrix, null)) ...
    

    or

    if((object)Matrix == null) ...
    
Sign up to request clarification or add additional context in comments.

4 Comments

Wont this "(object)Matrix" throw an exception if "Matrix" object is null? Just a thought.
@samar: No, it won't. You can cast a null reference to any reference type.
@samar further: as long as it is a reference-type, that is basically a no-op - it just forces the compiler to do a "load", "branch if true/false" (which means non-zero for references) rather than using any operators
@MarcGravell; Thank you very much for going a step further in explaining it for me.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.