Обнуляемые типы:лучший способ проверить наличие null или нуля в c#

StackOverflow https://stackoverflow.com/questions/633286

  •  08-07-2019
  •  | 
  •  

Вопрос

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

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);
}

Есть ли способ получше?

Это было полезно?

Решение

Мне нравится 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)), в противном случае, если value type является default(t), скажем, двойной false = 0d, для bool '\0', для char <=> и т. д.

Хотя мне вполне нравится принятый ответ, я думаю, что для полноты картины следует упомянуть и этот вариант:

if (item.Rate.GetValueOrDefault() == 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));
}

ПРИМЕЧАНИЕ нам не нужно проверять значение default (T) для null, поскольку мы имеем дело либо с типами значений, либо со структурами!Это также означает, что мы можем с уверенностью предположить, что T valueToCheck не будет равен null;Помните здесь, что Т?является ли сокращение Nullable<T> итак, добавив расширение к Nullable<T> мы получаем метод в int?, double?, bool?и т.д.

Примеры:

double? x = null;
x.IsNullOrDefault(); //true

int? y = 3;
y.IsNullOrDefault(); //false

bool? z = false;
z.IsNullOrDefault(); //true

Я согласен с использованием ?? оператор.

Если вы имеете дело со строками, используйте if (String.IsNullOrEmpty (myStr))

  

есть ли лучший способ?

Ну, если вы действительно ищете лучший способ, вы можете добавить еще один уровень абстракции поверх Rate. Ну вот кое-что, что я только что придумал, используя 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) { }
    }
}

Ваш пример кода не удастся. Если obj имеет значение null, то obj.ToString () приведет к исключению нулевой ссылки. Я бы сократил процесс и проверил наличие нулевого объекта в начале вашей вспомогательной функции. Что касается вашего фактического вопроса, какой тип вы проверяете на ноль или ноль? На String есть отличная функция IsNullOrEmpty, мне кажется, что это было бы отличным использованием методов расширения для реализации метода IsNullOrZero в int? тип.

Изменить: Помните, "?" это просто сахар компилятора для типа INullable, так что вы, вероятно, могли бы взять INullable в качестве параметра и затем сравнить его со значением null (parm == null), а если нет, сравнить со значением ноль.

public static bool nz(object obj)
{
    return obj == null || obj.Equals(Activator.CreateInstance(obj.GetType()));
}
class Item{  
 bool IsNullOrZero{ get{return ((this.Rate ?? 0) == 0);}}
}

Не забывайте, что для строк вы всегда можете использовать:

String.IsNullOrEmpty(str)

Вместо:

str==null || str==""
scroll top