Типы с нулевым значением: лучший способ проверить наличие нуля или нуля в c#
Я работаю над проектом, где я нахожу, я проверяю следующее во многих, многих местах:
if(item.Rate == 0 || item.Rate == null) { }
больше как любопытство, чем что-либо, каков лучший способ проверить для обоих случаев?
я добавил вспомогательный метод, который:
public static bool nz(object obj)
{
var parsedInt = 0;
var parsed = int.TryParse(obj.ToString(), out parsedInt);
return IsNull(obj) || (parsed && parsedInt == 0);
}
есть ли лучший способ?
10 ответов:
мне нравится
if ((item.Rate ?? 0) == 0) { }
обновление 1:
вы также можете определить метод расширения, например:
public static bool IsNullOrValue(this double? value, double valueToCheck) { return (value??valueToCheck) == valueToCheck; }
и использовать его так:
if(item.IsNullOrValue(0)){}
// но вы не получите много от него
использование дженериков:
static bool IsNullOrDefault<T>(T value) { return object.Equals(value, default(T)); } //... double d = 0; IsNullOrDefault(d); // true MyClass c = null; IsNullOrDefault(c); // true
если
T
это ссылка типа,value
по сравнению сnull
(default(T)
), в противном случае, еслиT
этоvalue type
, скажем, двухместный,default(t)
это 0d, для bool этоfalse
, для char-это''
и так далее...
хотя мне очень нравится принятый ответ, я думаю, что для полноты картины следует упомянуть и этот вариант:
if (item.Rate.GetValueOrDefault() == 0) { }
данное решение
- не требует дополнительного метода,
- быстрее, чем все остальные варианты, так как GetValueOrDefault-это операция чтения одного поля1 и
- читает легче, чем
((item.Rate ?? 0) == 0)
(это может быть дело вкуса, правда).
1 Этот однако это не должно влиять на ваше решение, поскольку эти виды микрооптимизации вряд ли будут иметь какое-либо значение.
это действительно просто расширение принятого ответа Фредди Риоса только с использованием дженериков.
public static bool IsNullOrDefault<T>(this Nullable<T> value) where T : struct { return default(T).Equals( value.GetValueOrDefault() ); } public static bool IsValue<T>(this Nullable<T> value, T valueToCheck) where T : struct { return valueToCheck.Equals((value ?? valueToCheck)); }
Примечание нам не нужно проверять значение по умолчанию(T) для null, так как мы имеем дело с типами значений или структурами! Это также означает, что мы можем с уверенностью предположить, что T valueToCheck не будет null; помните здесь, что T? является ли стенография Nullable
поэтому, добавив расширение к Nullable , мы получаем метод в int?, двойной?, типа bool? так далее. примеры:
double? x = null; x.IsNullOrDefault(); //true int? y = 3; y.IsNullOrDefault(); //false bool? z = false; z.IsNullOrDefault(); //true
Я согласен с использованием ?? оператор.
Если вы имеете дело со строками, используйте if (String.IsNullOrEmpty(myStr))
вы пример кода не удастся. Если obj является нулем тогда и OBJ.ToString () приведет к исключению нулевой ссылки. Я бы сократил процесс и проверил наличие нулевого объекта в начале вашей вспомогательной функции. Что касается вашего фактического вопроса, какой тип вы проверяете на нуль или ноль? В строке есть отличная функция IsNullOrEmpty, мне кажется, это было бы отличным использованием методов расширения для реализации метода IsNullOrZero на int? тип.
Edit: помните,'?- это просто сахар компилятора для типа INullable, поэтому вы, вероятно, можете взять INullable как parm, а затем jsut сравнить его с null (parm == null), а если не null, сравнить с нулем.
есть ли лучший способ?
Ну, если вы действительно ищете лучший способ, вы, вероятно, можете добавить еще один уровень абстракции поверх скорости. Ну вот то, что я только что придумал, используя Nullable Design Pattern.
using System; using System.Collections.Generic; namespace NullObjectPatternTest { public class Program { public static void Main(string[] args) { var items = new List { new Item(RateFactory.Create(20)), new Item(RateFactory.Create(null)) }; PrintPricesForItems(items); } private static void PrintPricesForItems(IEnumerable items) { foreach (var item in items) Console.WriteLine("Item Price: {0:C}", item.GetPrice()); } } public abstract class ItemBase { public abstract Rate Rate { get; } public int GetPrice() { // There is NO need to check if Rate == 0 or Rate == null return 1 * Rate.Value; } } public class Item : ItemBase { private readonly Rate _Rate; public override Rate Rate { get { return _Rate; } } public Item(Rate rate) { _Rate = rate; } } public sealed class RateFactory { public static Rate Create(int? rateValue) { if (!rateValue || rateValue == 0) return new NullRate(); return new Rate(rateValue); } } public class Rate { public int Value { get; set; } public virtual bool HasValue { get { return (Value > 0); } } public Rate(int value) { Value = value; } } public class NullRate : Rate { public override bool HasValue { get { return false; } } public NullRate() : base(0) { } } }