2011-01-31 5 views
9

Каков наиболее эффективный способ проверки нулевых ссылок на объекты? Я видел различные примеры кода, которые имеют разные способы проверки того, какой из них наиболее эффективен или тот, который считается наилучшей практикой?Что такое хорошая практика для проверки нулевой ссылки?

Object.ReferenceEquals(item, null) 

item == null 

item != null 

Object.Equals(item, null) 

благодаря

+4

Пусть один из них в 10 раз медленнее, чем другие, и вы ее использовали. Вы заметили бы? Только если бы это было в редкой дорогостоящей горячей точке. –

+1

@MikeDunlavey: Конечно, было бы совершенно глупо выбирать ту, которая в 10 раз медленнее по сравнению с любыми другими представленными параметрами (при условии, что другие параметры семантически правильны). Оптимизация не является преждевременной, если альтернатива была бы голодной и не принесла бы с собой никакой дополнительной выгоды. –

+2

@EdS .: Может быть, это придурок и головокружение, но люди делают это все время, и все в порядке, если это код, где производительность не является проблемой. Всякий раз, когда люди «новые» ничего, они тратят ведра циклов, и если они используют интерпретируемый язык, они платят 1-2 порядка величины скорости. –

ответ

8
  1. Object.ReferenceEquals(item, null) сравнить ссылки и равных до item == null.
  2. Object.Equals(item, null) сравнить ссылки для ссылочных типов и побитовые для типов значений, но в рефлекторе он равен (item == null) || ((item != null && null != null) && item.Equals(null)).
  3. item != null код не всегда равен !(item == null), но, конечно, результат должен быть равен.
  4. item == null код не равен null == item, он похож на typeof(item).Equals(object) и object.Equals(typeof(item)) метод звонков.

Он отличается, потому что вы можете переопределить !=, ==, Equals. Использовать методы с известной реализацией, null == item лучше кодировать, но труднее читать. Object.ReferenceEquals(null, item) может быть быстрее или нет.

P.S. use string.IsNullOrEmpty (item) тоже

+0

'null == item' is * not * труднее для чтения, а во многих языках c-стиля это более эффективная практика, потому что привычка исключает возможность создания задания при сравнении. Конечно, компилятор C# лает на вас, если вы попытаетесь выполнить задание в условном выражении. Но я все же утверждаю, что это хорошая практика. Я не тестировал, но в пункте № 4, хотя и не идентичен, сравнения, безусловно, эквивалентны, и все те же операции выполняются, поэтому я был бы очень удивлен, если бы была разница в производительности. – Craig

0

Во-первых 2 такие же эффективно.

Последнее, однако, не только выполняет контрольную проверку и не должно использоваться для проверки нуля.

2

Я всегда использую

item != null 

, но это сложнее, чем читать

item == null 

Object.ReferenceEquals используется для проверки двух объектов, являются ли тот же экземпляр.

+1

Как вы оцениваете '! =' труднее читать, чем '=='? –

+1

В зависимости от того, какой шрифт вы используете, восклицательный знак менее заметен, чем знак равенства. например, это меньше пикселей! чем =, если, например, вы использовали в (! bool), легче пропустить, чем (bool = false) зависит от того, есть ли у вас какой-либо слабовидящий персонал или нет, я полагаю! – WraithNath

+1

Если это * когда-либо было проблемой для вас, похоже, вам нужно переключать шрифты в вашу среду IDE. –

5

Для сравнения с null, я бы использовать == или != всегда, потому что для null он всегда должен дать тот же результат, как и ReferenceEqualsEquals в любом случае (так что нет необходимости в дополнительном коде).

Edit: Это правда, что == может быть изменено, чтобы дать неправильный результат для null (т.е. true), но это означает, что коррекция ошибок. Чтобы сделать код читаемым, я бы придерживался == и !=.

+1

-1, не всегда. Он может отличаться от .ReferenceEquals, если эти операторы перегружены (бессознательно) – nawfal

+0

nawfal, конечно, вы правы - это возможно только в бессмысленной (неправильной) переопределении оператора '=='. Я предпочел бы полагаться на '==' не подделка и иметь возможность писать гораздо более читаемый код (например, 'null! = Obj' в отличие от' false == Object.ReferenceEquals (obj, null) ') – sinelaw

+0

, но никогда не знаешь. И приведенный выше код можно сконденсировать в '! ReferenceEquals (obj, null)' или даже лучше использовать метод расширения. Просто говорю. – nawfal

3

ReferenceEquals равнозначно (object)o1==(object)o2. Это может быть быстрее, чем o1==o2, если оператор равенства перегружен. Object.Equals, вероятно, немного медленнее.

Разница между == и != не является производительностью, а как должна выглядеть ваша программа. Они могут быть немного медленнее, если операторы == и != перегружены.

Но я не думаю, что разница в производительности между ними имеет значение. Я бы выбрал тот, который легче всего читать. И это обычно == или !=.

Если я бросаю исключение я обычно использую == как в:

if(o == null) 
    throw new ...; 

If null результаты в не-оп, то обычно != подходит

if(x != null) 
{ 
    ... 
} 
+0

Хм. 'ReferenceEquals', эквивалентный' (object) o1 == (object) o2' полагается на явные знания о том, что оператор сравнения типа System.Object выполняет сравнительное сравнение. Конечно, может быть, хороший программист должен это знать. Но он чувствует себя «умным» и поэтому слегка неясным, если вы просматриваете код для понимания. Я не имею в виду неуважение, заявив об этом, но я бы благосклонно относился к умному всякий раз, когда это было разумно. – Craig

3

В дополнение, не забудьте заключить контракты с кодом в .NET 4.0!

System.Diagnostics.Contracts.Contract.Requires(item != null); 

Это не только красиво и понятно, но и позволяет проверять время компиляции. См. Code Contracts в msdn.

2

1)

Object.ReferenceEquals(item, null) 

Это хороший способ. Не так лаконично, как хотелось бы, но все равно великолепно, и он точно говорит о намерениях.

2)

item == null 

item != null 

Там нет ничего плохого в этом (который является самым элегантным), если вы уверены, что == и впоследствии != правильно перегружен. Его легко писать (перегружать) плохие операторы равенства (и часто делаются). Но настоящая проблема заключается в том, что вы пытаетесь перегрузить оператор == в классе (скажем, из семантического значения). Вы не можете использовать == для нулевых проверок внутри == функция перегрузки класса since that will cause an infinite recursion. Чтобы иметь один последовательный стиль, я полагаюсь на что-то другое.

3)

Object.Equals(item, null) 

Опять внутренне делает ReferenceEquals так что нет особого смысла, но если это семантически имеет смысл для вас, то идти с этим.

4)

Мой подход, чтобы сделать

(object)item == null 

, на которой я, опираясь на собственный оператор равенства object «s, который не может пойти не так. Не так читаемым, так что я просто завернуть в методе пользовательского расширения и перегрузки:

public static bool IsNull<T>(this T obj) where T : class 
{ 
    return (object)obj == null; 
} 

public static bool IsNull<T>(this T? obj) where T : struct 
{ 
    return !obj.HasValue; 
} 

Это имеет смысл, так как мне нужно будет проверить на DBNull слишком часто. Итак, теперь у меня есть единый стиль во всем!

public static bool IsNull<T>(this T obj) where T : class 
{ 
    return (object)obj == null || obj == DBNull.Value; 
} 

(Не снимать (object) отливку, как это то, что позволит предотвратить зацикливание при перегрузке ==, как указано выше)

Дополнительно ограничение предотвращает IsNull на типы значений. Теперь его, как сладко, как вызов

object obj = new object(); 
Guid? guid = null; 
bool b = obj.IsNull(); // false 
b = guid.IsNull(); // true 
2.IsNull(); // error 

Я также нашел (object)item == null является very very very slightly faster than Object.ReferenceEquals(item, null) или object.Equals(,) по этому вопросу, но только если это имеет значение (я в настоящее время работает над чем-то, где я микро-оптимизации все!) ,

Чтобы увидеть полное руководство по вопросам осуществления проверки равенства см What is "Best Practice" For Comparing Two Instances of a Reference Type?

Смежные вопросы