views:

139

answers:

2

The following doesn't compile:

public void MyMethod<T>(T value)
{
    if (value == default(T))
    {
        // do stuff
    }
}

Error: Operator '==' cannot be applied to operands of type 'T' and 'T'

I can't use value == null because T may be a struct.
I can't use value.Equals(default(T)) because value may be null.
What is the proper way to test for equality to the default value?

+6  A: 

What about

object.Equals(value, default(T))
Ngu Soon Hui
I knew it should be simple. Thank you.
Greg
+1. Tested. Works correctly with various types: `MyMethod(0); MyMethod<String>(null); MyMethod<DataSet>(null);` - in each case returns true.
Roman Boiko
+4  A: 

To avoid boxing for struct / Nullable<T>, I would use:

if (EqualityComparer<T>.Default.Equals(value,default(T))
{
    // do stuff
}

This supports any T that implement IEquatable<T>, using object.Equals as a backup, and handles null etc (and lifted operators for Nullable<T>) automatically.

There is also Comparer<T>.Default which handles comparison tests. This handles T that implement IComparable<T>, falling back to IComparable - again handling null and lifted operators.

Marc Gravell
Are you saying that `EqualityComparer<T>.Default.Equals` has better performance than `Object.Equals`, or that it would give a correct value in some case that `Object.Equals` wouldn't?
Greg
Better performance (less boxing); consider `T=int`; to call `object.Equals` it has to box `value` and `default(T)` - that's two extra heap allocations + GC. Using `EqualityComparer<T>` it has 3 different underlying implementations - `class`, `Nullable<T>` and `struct` - it can then do everything (including `null` tests) without **any** boxing. The work of figuring out which implementation to use is only done once per type and cached, so still very fast.
Marc Gravell
Thank you, Marc! Your explanation is wonderful
Greg