什么更好:身份证? 0 == 0或id == null || id == 0?

时间:2011-02-10 12:14:08

标签: c# performance c#-4.0

因为我有

public class Foo
{
  public int? Id { get; set; }
}

什么更好

if ((Id ?? 0) == 0) {}

if (Id == null || Id == 0)

8 个答案:

答案 0 :(得分:4)

我推荐第二个。它更具可读性。

正如我所注意到的,很少有人熟悉??运营商。

答案 1 :(得分:4)

if(Id.GetValueOrDefault() == 0)

也是一种选择。在性能方面,我怀疑是否存在任何真正的差异,无论如何你都会进行微优化,这很少有益。

答案 2 :(得分:2)

我每次都喜欢可读性而不是聪明(几乎),所以我肯定会选择:if (Id == null || Id == 0)

答案 3 :(得分:2)

更好的是:

   if(!Id.HasValue || Id == 0)
   {
   }

答案 4 :(得分:2)

由于这是标记为“性能”,这里是我对这些主题的一般建议,我认为这些主题在这里是有效的:

  1. 衡量,衡量,衡量
  2. 不要进行微量优化,除非这是你能做的最后一件事,而且还需要从核心循环中获得几个循环
  3. 扩展:

    您的代码中可能存在一些使得此类微优化提示无效或非最佳的内容,因此您在性能方面的最佳选择就是衡量它。确保你测量一个循环的足够迭代,因为测量小代码1次会受到你的机器使整个运动无效的所有其他事情的干扰。

    对于微优化,不要担心。选择你(以及其他任何人将要维护代码)的人最为舒适,并且如果你真的需要,那么就要担心微观优化。

    我个人经常写第一个,即

    if (o ?? 0 == 0)
    

    或者,对于字符串:

    if ((s ?? string.Empty).Length == 0)
    

    然而,就可读性和“看起来最好”而言,这是一个双重问题。随心所欲,随心所欲,继续探讨更大的问题。

    编辑,好吧,在最后一个代码示例之前,我在某处停止思考。我结合了两件不同的事情:

    1. 除非有用,否则我永远不会将字符串属性和字段保留为null
    2. 从1开始,我可以if (PropertyName.Length == 0)
    3. 当然,在该特定示例中,我将使用以下两种方法之一:

      1. if (string.IsNullOrEmpty(s))
      2. if (string.IsNullOrWhiteSpace(s))(仅限4.0,仅在您需要时)

答案 5 :(得分:1)

如果您正在使用此代码一次,那么使用它的区别并不大(但是,我更喜欢第二个 - 它更具可读性)。否则,我想给出一些我在这里验证的条件名称。 E.g。

public class Foo
{
  public int? Id { get; set; }

  public bool IsNew
  {
    get
    {
        return (Id == null) || (Id == 0);
    }
  }
}

现在代码说出你要验证的内容。它可以像书一样阅读

if (IsNew) {}

答案 6 :(得分:1)

我认为在你的情况下,第一个例子可以快一点。

我在LinqPad中以两种方式做到了这一点

void Main()
{
    Foo f = new Foo();
    if ((Id ?? 0) == 0) {} // if (f.Id == null || f.Id == 0) {}
}

// Define other methods and classes here
public class Foo
{
  public int? Id { get; set; }
}

if ((Id ?? 0) == 0) {}的IL如下:

IL_0000:  newobj      UserQuery+Foo..ctor
IL_0005:  stloc.0     
IL_0006:  ldloc.0     
IL_0007:  callvirt    UserQuery+Foo.get_Id
IL_000C:  stloc.1     
IL_000D:  ldloca.s    01 
IL_000F:  call        System.Nullable<System.Int32>.get_HasValue
IL_0014:  brtrue.s    IL_0019
IL_0016:  ldc.i4.0    
IL_0017:  br.s        IL_0020
IL_0019:  ldloca.s    01 
IL_001B:  call        System.Nullable<System.Int32>.GetValueOrDefault

Foo.get_Id:
IL_0000:  ldarg.0     
IL_0001:  ldfld       UserQuery+Foo.<Id>k__BackingField
IL_0006:  ret         

Foo.set_Id:
IL_0000:  ldarg.0     
IL_0001:  ldarg.1     
IL_0002:  stfld       UserQuery+Foo.<Id>k__BackingField
IL_0007:  ret         

Foo..ctor:
IL_0000:  ldarg.0     
IL_0001:  call        System.Object..ctor
IL_0006:  ret    

if (f.Id == null || f.Id == 0)的IL低于 - 请注意两次调用get_HasValue

IL_0000:  newobj      UserQuery+Foo..ctor
IL_0005:  stloc.0     
IL_0006:  ldloc.0     
IL_0007:  callvirt    UserQuery+Foo.get_Id
IL_000C:  stloc.1     
IL_000D:  ldloca.s    01 
IL_000F:  call        System.Nullable<System.Int32>.get_HasValue
IL_0014:  brfalse.s   IL_0031
IL_0016:  ldloc.0     
IL_0017:  callvirt    UserQuery+Foo.get_Id
IL_001C:  stloc.2     
IL_001D:  ldloca.s    02 
IL_001F:  call        System.Nullable<System.Int32>.GetValueOrDefault
IL_0024:  brtrue.s    IL_002F
IL_0026:  ldloca.s    02 
IL_0028:  call        System.Nullable<System.Int32>.get_HasValue
IL_002D:  br.s        IL_0030
IL_002F:  ldc.i4.0    

Foo.get_Id:
IL_0000:  ldarg.0     
IL_0001:  ldfld       UserQuery+Foo.<Id>k__BackingField
IL_0006:  ret         

Foo.set_Id:
IL_0000:  ldarg.0     
IL_0001:  ldarg.1     
IL_0002:  stfld       UserQuery+Foo.<Id>k__BackingField
IL_0007:  ret         

Foo..ctor:
IL_0000:  ldarg.0     
IL_0001:  call        System.Object..ctor
IL_0006:  ret         

也许我应该多出更多!

答案 7 :(得分:-2)

我建议第二个也应该优先考虑以下代码

 if (null == Id || 0 == Id)