Nullable 형식 : C #에서 null 또는 0을 확인하는 더 좋은 방법


85

저는 여러 곳에서 다음 사항을 확인하는 프로젝트를 진행하고 있습니다.

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

더 좋은 방법이 있습니까?

답변:


161

나는 좋아 if ((item.Rate ?? 0) == 0) { }

업데이트 1 :

다음과 같은 확장 메서드를 정의 할 수도 있습니다.

public static bool IsNullOrValue(this double? value, double valueToCheck)
{
    return (value??valueToCheck) == valueToCheck;
}

다음과 같이 사용하십시오.

if(item.IsNullOrValue(0)){} //하지만 당신은 그것으로부터 많은 것을 얻지 못합니다


3
감사합니다-매우 간결합니다! 나는 가독성에 관심이 있었지만 실제로 그것을 이해했다면 완벽하게 읽을 수 있다는 결론에 도달했습니다. 운영자.
nailitdown

2
확장 방법을 사용해야합니다. 작성하는 순간에는 읽을 수 있지만이 작은 코드 덩어리에는 약간의 생각이 필요합니다. 즉, 코드를 읽고 사용하면 주요 문제에서주의가 산만 해집니다.
피규

11
@nailitdown : 실제로는 아닙니다. Nullable <T>에 대한 확장 메서드가 필요합니다. 더블? Nullable <double>의 별칭입니다. 서명은 다음과 같습니다. public static bool IsNullOrValue <T> (this Nullable <T>, t valueToCheck) 여기서 T : struct
Joshua Shannon

3
@nailitdown : (파트 II) return 문은 return (value ?? default (T)). Equals (valueToCheck);
Joshua Shannon

2
당신이 "IsNullOr (0)"로 단축하면 자연스럽게 "null 또는 제로"로 읽을 것
ChrisFox

41

제네릭 사용 :

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는 A의 참조 형 , value비교한다 null( default(T)), 그렇지 않은 경우 TA는 value type,의 두 번 가정 해 봅시다 default(t)부울이 들어 0D입니다 false문자이기 때문이다, '\0'등등 ...


1
확장 방법 :public static bool IsNullOrValue<T>(this T? value, T valueToCheck) where T : struct { return (value ?? default(T)).Equals(valueToCheck); }
Behzad Ebrahimi

39

나는 받아 들여지는 대답을 아주 좋아하지만 완전성을 위해이 옵션도 언급해야한다고 생각합니다.

if (item.Rate.GetValueOrDefault() == 0) { }

이 솔루션

  • 추가 방법이 필요하지 않습니다.
  • GetValueOrDefault는 단일 필드 읽기 작업 ¹ 이므로 다른 모든 옵션보다 빠릅니다.
  • 보다 쉽게 ​​읽습니다 ((item.Rate ?? 0) == 0)(하지만 이것은 취향의 문제 일 수 있습니다).

¹하지만 이러한 종류의 마이크로 최적화는 아무런 차이가 없을 가능성이 높기 때문에 결정에 영향을주지 않습니다.


19

이것은 Generics를 사용하는 Freddy Rios의 대답의 확장 일뿐입니다.

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

참고로 값 유형이나 구조체를 다루기 때문에 null에 대해 default (T)를 확인할 필요가 없습니다! 이것은 또한 T valueToCheck가 null이 아니라고 안전하게 가정 할 수 있음을 의미합니다. 여기 T 기억 나? 속기 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


2

더 좋은 방법이 있습니까?

글쎄, 정말로 더 나은 방법을 찾고 있다면 아마도 Rate 위에 또 다른 추상화 레이어를 추가 할 수 있습니다. Nullable Design Pattern을 사용하여 방금 생각해 낸 것이 있습니다.

시스템 사용;
System.Collections.Generic 사용;

네임 스페이스 NullObjectPatternTest
{
    공개 수업 프로그램
    {
        public static void Main (string [] args)
        {
            var items = 새 목록
                            {
                                새 항목 (RateFactory.Create (20)),
                                새 항목 (RateFactory.Create (null))
                            };

            PrintPricesForItems (items);
        }

        private static void PrintPricesForItems (IEnumerable items)
        {
            foreach (항목의 var 항목)
                Console.WriteLine ( "항목 가격 : {0 : C}", item.GetPrice ());
        }
    }

    공용 추상 클래스 ItemBase
    {
        public abstract Rate Rate {get; }
        public int GetPrice ()
        {
            // Rate == 0인지 Rate == null인지 확인할 필요가 없습니다.
            return 1 * Rate.Value;
        }
    }

    공용 클래스 Item : ItemBase
    {
        개인 읽기 전용 Rate _Rate;
        public override Rate Rate {get {return _Rate; }}
        public Item (Rate rate) {_Rate = rate; }
    }

    공개 봉인 클래스 RateFactory
    {
        public static Rate Create (int? rateValue)
        {
            if (! rateValue || rateValue == 0) 
                return new NullRate ();
            return new Rate (rateValue);
        }
    }

    공개 클래스 비율
    {
        public int Value {get; 세트; }
        public virtual bool HasValue {get {return (Value> 0); }}
        public Rate (int value) {Value = value; }
    }

    공용 클래스 NullRate : 비율
    {
        public override bool HasValue {get {return false; }}
        public NullRate () : base (0) {}
    }
}

1
나는 일부 이전 단계에서 널 (null) 값을 제거하여 이동하는 방법이 있었던 것이 당신에게 맞아요 생각
nailitdown

정확히. "리팩토링"이라는 개념이 있습니다. 더 나은 패턴이나 더 나은 구조로 코드를 리팩토링 할 수 있습니다. 이후 단계에서 항상 nullable 값을 제거 할 수 있습니다 .
dance2die

2

코드 샘플은 실패합니다. obj가 null이면 obj.ToString ()은 null 참조 예외를 발생시킵니다. 프로세스를 단축하고 도우미 함수 시작시 null obj를 확인합니다. 실제 질문에 관해서는 null 또는 0을 확인하는 유형이 무엇입니까? String에는 훌륭한 IsNullOrEmpty 함수가 있습니다. 이것은 확장 메서드를 사용하여 int에 IsNullOrZero 메서드를 구현하는 데 유용 할 것 같습니다. 유형.

편집 : 기억하세요, '?' INullable 유형에 대한 컴파일러 설탕이므로 INullable을 parm으로 취한 다음 jsut을 null (parm == null)과 비교할 수 있으며 null이 아니면 0과 비교합니다.


그 버그를 잡은 것에 대한 환호-이 프로젝트에서 나는 int ?, double ?, decimal ?, 등등에 대해 확인해야합니다. 이것이 내가 "object"를 사용하는 이유입니다
nailitdown

기억하세요, '?' INullable <T> 유형에 대한 컴파일러 설탕이므로 INullable <T>를 매개 변수로 취한 다음 jsut을 null (parm == null)과 비교할 수 있으며 null이 아닌 경우 0과 비교할 수 있습니다.
Walden Leverich

0
public static bool nz(object obj)
{
    return obj == null || obj.Equals(Activator.CreateInstance(obj.GetType()));
}

1
반사가 느리므로 이와 같은 솔루션에주의하십시오. 나는 성찰에 반대하지 않지만, 이와 같은 "간단한"기능에서 그것을 기대하지 않을 것이고 그것은 나를 경계하게 할 것이다.
Walden Leverich

이것은 실제로 0을 확인합니까?
nailitdown

사실은 아닙니다. Activator.CreateInstance (obj.GetType ())는 nullable 형식에 대해 null을 반환합니다.
피규

@configurator : nullable 유형이 boxed되면 기본 구조체로 boxing됩니다.
Eamon Nerbonne

0
class Item{  
 bool IsNullOrZero{ get{return ((this.Rate ?? 0) == 0);}}
}

귀하의 솔루션은 하나의 속성에 대해 작동합니다. 동일한 항목의 많은 속성이 null / zero를 확인하도록 지정
했어야

0

잊지 마세요. 문자열의 경우 항상 다음을 사용할 수 있습니다.

String.IsNullOrEmpty(str)

대신에:

str==null || str==""

1
질문은 빈 문자열이 아닌 "0"과 비교됩니다.
dance2die

-1

Joshua Shannon 의 좋은 대답 에서 한 걸음 더 나아 갑니다. 이제 boxing / unboxing 방지 :

public static class NullableEx
{
    public static bool IsNullOrDefault<T>(this T? value)
        where T : struct
    {
        return EqualityComparer<T>.Default.Equals(value.GetValueOrDefault(), default(T));
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.