Thursday, December 18, 2008

 

Comparing Default Values In Generic Classes

Ever since they were introduced in C# 2.0, most programmers have loved generics. I know I do! But, it can be a bit tricky to determine if a variable has been assigned or is still the default value if you do not know how to do it.

Consider the following class, and note that it



public class MyClass
{
private T _field;

public MyClass()
{
_field = default(T);
}

public T Field
{
get
{
return _field;
}
set
{
_field = value;
}
}

public bool IsDefaultValue
{
get
{
// The following line does not compile!
return ( _field == default(T) );
}
}
}
 

The code default(T) causes the compiler to use the default that is appropriate for the type (null for refrence types, 0 for an int, 0.0 for a double, etc.). This is used in the constructor to assign the default value to _field. Therefore, it seems logical that we can do a comparison such as ( _field == default(T) ). But, the compiler does not like it and will complain with a message like Operator '==' cannot be applied to operands of type 'T' and 'T'.

So, the question becomes just how do you do such a comparison if you cannot do that? If you know T is a reference type, you can compare against null.


// Works only if T is a reference time
return ( _field == null );
 

But, that will only work for reference types and we have not put any such constraints on T.

Actually, as a side note, that code will compile for both reference types and value types but will always return false for value types. This is because, believe it or not, starting with C# 2.0, you can compare any value type to null using the == operator, but the comparison will always return false. This is a side effect of adding support for nullable types via ?.



int x = 1;
if (x == null)... // Always returns false

int? y = null;
if (y == null)... // Returns true since y is null

y = 1;
if (y == null)... // Return false since y is not null

if (x == y) ... // Return true since x and y have the same value of 1

 

So, if you cannot compare against default(T) or null, what can you do to see if _field is currently set to the default value? The best way I have found to do this is shown below.



public bool IsDefaultValue
{
get
{
return object.Equals(_field, default(T) );
}
}

 

With that change to the IsDefaultValue method, it compiles and works as you would expect.



MyClass<int> obj1 = new MyClass<int>();
bool flag1a = obj1.IsDefaultValue; // true
obj1.Field = 1;
bool flag1b = obj1.IsDefaultValue; // false

MyClass<object> obj2 = new MyClass<object>();
bool flag2a = obj2.IsDefaultValue; // true
obj2.Field = new object();
bool flag2b = obj1.IsDefaultValue; // false

 

Comments: Post a Comment





<< Home

This page is powered by Blogger. Isn't yours?

Subscribe to Posts [Atom]