带有Generics的C#:'default'关键字

时间:2009-04-10 14:26:58

标签: c# generics resharper

我编写了以下方法,从Serializable类(POCO)列表中返回一个Unserializable类(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 != null),并建议将其更改为:

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

我的问题是实际改进或阻止发生这种变化的原因是什么?我知道此上下文中的默认关键字必须对泛型做一些事情,但我不确定它代表什么准确。

PS。 UnSerializableEntitySerializableEntity是类泛型。

2 个答案:

答案 0 :(得分:13)

如果SerializableEntity是值类型,则永远不会是null。因此,if语句的正文将始终执行,因为它正在检查nulldefault关键字将返回泛型类型的默认值。对于参考类型,默认值为null。对于值类型,它为零(或该值类型的零代表)。

如果您只想将引用类型作为实体,则应该对通用参数设置约束。例如:

List<UnSerializableEntity> ToListOfUnserializables(List<SerializableEntity> entityList)
    where SerializableEntity : class

答案 1 :(得分:4)

肯特的回答是准确的,但要更明确地回答你关于Resharper的问题及其抱怨的原因:

对于引用类型(类),检查null就足够了,因为它被认为是引用类型的“默认”值。但是,对于值类型(例如结构),“default”将永远不为null。因此,由于您的SerializableEntity和UnSerializableEntity是泛型,您可以将它们指定为引用或值类型,因此null检查您的操作可能不是您想要的。你想要检查的是确保参数是你真正想要关注的东西。对于引用类型,您不希望自己关注null对象。对于值类型,您不希望自己关注“归零”值。

例如:假设您将DateTime指定为您正在处理的数据类型。你真的想要添加没有设置任何值的DateTimes吗? DateTime的默认值是1/1/0001,而不是null,因此您需要使用if (!Equals(e, default(SerializableEntity)))而不是if (e != null)

来检查