Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C#: 'default' keyword with Generics

I have written the following method to return a list of Unserializable classes (LINQ classes) from a list of Serializable classes (POCOs):

List<UnSerializableEntity> ToListOfUnserializables(List<SerializableEntity> entityList)
{
    var tempList = new List<UnSerializableEntity>();
    entityList.ForEach(e =>
    {
        if (e != null)
        {
            tempList.Add(ConvertFromSerializableToUnserializable(e));
         }
     });
     return tempList;
}

Now, Resharper has 'complained' about this line: if (e != null), and suggested to change it to this:

if (!Equals(e, default(SerializableEntity))) 

My question is to what has this change actually improved or prevented from happening? and I know the default keyword in this context has to do something with generics, but I'm not sure what it represents exactly.

PS. UnSerializableEntity and SerializableEntity are class generics.

like image 935
Andreas Grech Avatar asked Apr 10 '09 14:04

Andreas Grech


2 Answers

If SerializableEntity is a value type, it can never be null. Therefore, the body of your if statement will always execute because it is checking for null. The default keyword will return the default value of the generic type. For reference types, the default value is null. For value types, it is zero (or whatever zero represents for that value type).

If you only want reference types as entities, you should set constraints on your generic parameters. For example:

List<UnSerializableEntity> ToListOfUnserializables(List<SerializableEntity> entityList)
    where SerializableEntity : class
like image 136
Kent Boogaart Avatar answered Oct 20 '22 12:10

Kent Boogaart


Kent's response is accurate, but to answer your question more explicitly about Resharper and why it's complaining:

In the case of a reference type (class) a check for null would suffice, since that is considered the "default" value for a reference type. However, for a value type (such as a struct), the "default" will NEVER be null. Hence, since your SerializableEntity and UnSerializableEntity are generics, you can specify them to be either reference or value types, so the null check your doing is probably not what you want. What you would want to check is to make sure that the parameter is something that you really want to concern yourself with. In the case of a reference type, you don't want to concern yourself with null objects. In the case of a value type, you don't want to concern yourself with an "zeroed out" value.

For example: Say you specify a DateTime to be the data type you're dealing with. Do you really want to be adding DateTimes that do not have any value set? The default value for a DateTime is 1/1/0001, not null, so you would need to check for that using if (!Equals(e, default(SerializableEntity))) not if (e != null)

like image 33
Joseph Avatar answered Oct 20 '22 10:10

Joseph