C#: 泛型中使用的'default'关键字

7
我已经编写了以下方法,用于从可序列化类(POCOs)的列表中返回一组不可序列化类(LINQ类)的列表:

我编写了以下方法,用于从可序列化类(POCOs)的列表中返回一组不可序列化类(LINQ类)的列表:

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

现在,Resharper对这行代码提出了“抱怨”,建议更改为以下内容:if (e is object)
if (!Equals(e, default(SerializableEntity))) 

我的问题是,这个变化实际上改进或防止了什么?我知道在这种情况下,默认关键字与泛型有关,但我不确定它确切地代表什么。
PS。UnSerializableEntity和SerializableEntity是类泛型。
2个回答

13
如果SerializableEntity是一个值类型,它永远不可能为null。因此,您的if语句体将始终执行,因为它正在检查nulldefault 关键字将返回通用类型的默认值。对于引用类型,其默认值为null。对于值类型,它是零(或者对于该值类型表示零的任何内容)。
如果您只希望在实体中使用引用类型,则应在泛型参数上设置约束。例如:
List<UnSerializableEntity> ToListOfUnserializables(List<SerializableEntity> entityList)
    where SerializableEntity : class

但是他的if语句检查了该值是否不为空,那么这是否意味着它将始终执行? - sisve
“if”块永远不会执行:值类型将抛出异常。 - Joel Coehoorn
@Simon 当 e 不为 null/default 时,语句 e != null 和 !Equals(e, default(SerializableEntity)) 都是 true。 - Jesper Fyhr Knudsen
@Joel,如果“e”是值类型,则针对“null”的测试不会引发异常。您指的是其他异常吗? - bdukes

4
肯特的回答是准确的,但更明确地回答你关于Resharper为什么抱怨的问题:
对于引用类型(类),检查null就足够了,因为这被认为是引用类型的“默认”值。然而,对于值类型(如结构体),“默认”值永远不会是null。因此,由于您的SerializableEntity和UnSerializableEntity是泛型,您可以指定它们为引用类型或值类型,因此您正在进行的null检查可能不是您想要的。您想要检查的是确保参数是您真正关心的内容。对于引用类型,您不想关心空对象。对于值类型,您不想关心“零化”的值。
例如:假设您指定DateTime作为要处理的数据类型。您真的想添加没有设置任何值的DateTime吗?DateTime的默认值是1/1/0001,而不是null,因此您需要使用if (!Equals(e, default(SerializableEntity)))而不是if (e != null)来检查它。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接