[c#] 속성의 속성이 null인지 확인하는 C # 우아한 방법

C #에서는이 예제에서 PropertyC의 값을 가져 오려고하며 ObjectA, PropertyA 및 PropertyB는 모두 null 일 수 있습니다.

ObjectA.PropertyA.PropertyB.PropertyC

최소한의 코드로 PropertyC를 안전하게 얻으려면 어떻게해야합니까?

지금 확인합니다.

if(ObjectA != null && ObjectA.PropertyA !=null && ObjectA.PropertyA.PropertyB != null)
{
    // safely pull off the value
    int value = objectA.PropertyA.PropertyB.PropertyC;
}

이와 같은 (의사 코드) 더 많은 것을하는 것이 좋을 것입니다.

int value = ObjectA.PropertyA.PropertyB ? ObjectA.PropertyA.PropertyB : defaultVal;

null-coalescing 연산자로 훨씬 더 축소되었을 수 있습니다.

편집 원래 두 번째 예제는 js와 비슷하다고 말했지만 js에서 작동하지 않는다고 올바르게 지적 되었기 때문에 가짜 코드로 변경했습니다.



답변

C # 6에서는 Null 조건부 연산자를 사용할 수 있습니다 . 따라서 원래 테스트는 다음과 같습니다.

int? value = objectA?.PropertyA?.PropertyB?.PropertyC;


답변

짧은 확장 방법 :

public static TResult IfNotNull<TInput, TResult>(this TInput o, Func<TInput, TResult> evaluator)
  where TResult : class where TInput : class
{
  if (o == null) return null;
  return evaluator(o);
}

사용

PropertyC value = ObjectA.IfNotNull(x => x.PropertyA).IfNotNull(x => x.PropertyB).IfNotNull(x => x.PropertyC);

이 간단한 확장 방법은 http://devtalk.net/csharp/chained-null-checks-and-the-maybe-monad/에서 찾을 수 있습니다.

편집하다:

잠시 사용한 후에이 메서드의 적절한 이름 은 원래 With () 대신 IfNotNull () 이어야한다고 생각합니다 .


답변

수업에 메소드를 추가 할 수 있습니까? 그렇지 않다면 확장 방법 사용에 대해 생각해 보셨습니까? 라는 개체 유형에 대한 확장 메서드를 만들 수 있습니다 GetPropC().

예:

public static class MyExtensions
{
    public static int GetPropC(this MyObjectType obj, int defaltValue)
    {
        if (obj != null && obj.PropertyA != null & obj.PropertyA.PropertyB != null)
            return obj.PropertyA.PropertyB.PropertyC;
        return defaltValue;
    }
}

용법:

int val = ObjectA.GetPropC(0); // will return PropC value, or 0 (defaltValue)

그건 그렇고, 이것은 당신이 .NET 3 이상을 사용하고 있다고 가정합니다.


답변

당신이하는 방식은 정확합니다.

당신은 할 수 설명 된 것과 같은 트릭을 사용 여기 의 LINQ 표현을 사용하여 :

int value = ObjectA.NullSafeEval(x => x.PropertyA.PropertyB.PropertyC, 0);

그러나 각 속성을 수동으로 확인하는 것이 훨씬 느립니다.


답변

데메테르법칙 을 준수하기위한 리팩터링


답변

2014 업데이트 : C # 6에는 ?.‘안전한 탐색’또는 ‘널 전파’라는 다양한 새 연산자가 있습니다.

parent?.child

읽기 http://blogs.msdn.com/b/jerrynixon/archive/2014/02/26/at-last-c-is-getting-sometimes-called-the-safe-navigation-operator.aspx를 자세한 내용은

이것은 오랫동안 큰 인기를 요청하고있다
https://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/3990187-add-operator-to-c-?tracking_code=594c10a522f8e9bc987ee4a5e2c0b38d


답변

분명히 Nullable Monad를 찾고 있습니다 .

string result = new A().PropertyB.PropertyC.Value;

된다

string result = from a in new A()
                from b in a.PropertyB
                from c in b.PropertyC
                select c.Value;

nullnullable 속성이 null이면을 반환합니다 . 그렇지 않으면 Value.

class A { public B PropertyB { get; set; } }
class B { public C PropertyC { get; set; } }
class C { public string Value { get; set; } }

LINQ 확장 방법 :

public static class NullableExtensions
{
    public static TResult SelectMany<TOuter, TInner, TResult>(
        this TOuter source,
        Func<TOuter, TInner> innerSelector,
        Func<TOuter, TInner, TResult> resultSelector)
        where TOuter : class
        where TInner : class
        where TResult : class
    {
        if (source == null) return null;
        TInner inner = innerSelector(source);
        if (inner == null) return null;
        return resultSelector(source, inner);
    }
}