Что лучше: id? 0 == 0 или id == ноль || id == 0? - PullRequest
1 голос
/ 10 февраля 2011

Так как у меня

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

Что лучше

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

или

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

?

Ответы [ 8 ]

4 голосов
/ 10 февраля 2011
if(Id.GetValueOrDefault() == 0)

Также вариант. С точки зрения производительности, я сомневаюсь, что есть какая-то реальная разница, и в любом случае вы будете заниматься микрооптимизацией, что редко бывает полезным.

4 голосов
/ 10 февраля 2011

Я рекомендую второй. Это более читабельно.

И, как я заметил, меньше людей знакомы с оператором ??.

2 голосов
/ 10 февраля 2011

Так как это помечено как «производительность», вот мой общий совет по таким темам, который я все еще считаю действительным здесь:

  1. Мера, мера, мера
  2. Не занимайтесь микрооптимизацией, если это не последнее, что вы можете сделать, и все же вам нужно вытащить несколько циклов из цикла ядра

Расширить:

Вполне возможно, что в вашем коде есть вещи, которые делают такие советы по микрооптимизации недействительными или неоптимальными, поэтому ваш лучший выбор в отношении производительности - просто измерить его. Убедитесь, что вы измеряете достаточное количество итераций цикла, так как измерение того, что небольшой код 1 раз будет мешать всем остальным вещам, которые ваша машина делает недействительным для всего упражнения.

Что касается микрооптимизации, не беспокойтесь об этом. Выберите тот, который вам (и тому, кто еще будет поддерживать код), наиболее удобен, и подумайте о микрооптимизации, если и когда вам это действительно нужно.

Лично я часто пишу первое, т. Е.

if (o ?? 0 == 0)

или, в случае строк:

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

Однако, с точки зрения читабельности и «того, что выглядит лучше», это сложная проблема. Иди с тем, что ты хочешь, чувствуешь себя комфортно и переходи к более крупным проблемам.

Edit , Хорошо, я перестал думать где-то перед последним примером кода. Я объединил две разные вещи, которые я делаю:

  1. Я никогда не оставляю строковые свойства и поля как null, если это не полезно
  2. С 1. Я могу сделать if (PropertyName.Length == 0)

Конечно, в этом конкретном примере я бы использовал один из следующих двух:

  1. if (string.IsNullOrEmpty(s))
  2. if (string.IsNullOrWhiteSpace(s)) (только в 4.0 и только если вам нужно)
2 голосов
/ 10 февраля 2011

Еще лучше было бы:

   if(!Id.HasValue || Id == 0)
   {
   }
2 голосов
/ 10 февраля 2011

Я предпочитаю удобочитаемость, а не хитрость (почти) каждый раз, поэтому я определенно выберу: if (Id == null || Id == 0)

1 голос
/ 10 февраля 2011

Я считаю, что в вашем случае первый пример мог бы быть немного быстрее.

Я сделал это обоими способами в 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; }
}

IL для if ((Id ?? 0) == 0) {} выглядит следующим образом:

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    

IL для if (f.Id == null || f.Id == 0) ниже - обратите внимание на два вызова 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         

Может быть, мне следует выбраться побольше!

1 голос
/ 10 февраля 2011

Если вы используете этот код один раз, разница в том, что использовать, невелика (но я бы предпочел второй - он более читабелен).В противном случае, я хотел бы дать какое-то имя условия, которое я проверяю здесь.Например,

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

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

Теперь код говорит о том, что вы проверяете.И это читается как книга

if (IsNew) {}
0 голосов
/ 10 февраля 2011

Я рекомендую второй, и код должен предпочтительно выглядеть следующим образом

 if (null == Id || 0 == Id)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...