부울 식에서 null 조건부 연산자를 사용하는 최적의 방법


11

다음과 같은 부울 표현식을 작성 중입니다.

team.Category == "A Team" && team?.Manager?.IsVietnamVet

public class Manager
{
    public bool IsVietnamVet { get; set; }
}

public class Team
{
    public string Category { get; set; }

    public Manager Manager { get; set; }
}

... 오류가 발생합니다.

'bo &'연산자는 'bool'및 'bool?'유형의 피연산자에 적용 할 수 없습니다.

그것을 처리하는 가장 최적의 방법은 무엇입니까?

  1. team.Category == "A Team" && (team?.Manager?.IsVietnamVet ?? false)

    정말 읽을 수 있습니까?

  2. team.Category == "A Team" && (team?.Manager?.IsVietnamVet).GetValueOrDefault()

    LINQ-to-Entities에서는 작동하지 않을 수 있습니다 ...

  3. team.Category == "A Team" && team?.Manager?.IsVietnamVet == true

    if (condition == true)망설임없이 쓰시겠습니까 ?

다른 옵션이 있습니까? 작성하는 것이 궁극적으로 더 낫습니까?

  1. team.Category == "A Team" && team.Manager != null && team.Manager.IsVietnamVet

if (! (String.IsNullOrEmpty (team.Manager) && condition)) ...
스눕

1
@StevieV 그것은 처음부터 이런 식으로 ment이었다;)
Santhos

1
코드를보다 신중하게 살펴보면 null 조건부 부분은이어야합니다 team.Manager?.IsVietnamVet. 즉 team, 이후 에는 null 조건부 여야 null합니다.
svick

2
"주저없이 if (condition == true)를 쓰시겠습니까?" 일반적인 부울의 경우에는 불필요하기 때문에 아니오입니다. 그러나 nullable boolean의 경우 이는 관련이 있습니다. nullableBool == true기본적으로 테스트 중입니다 nullableBool != false && nullableBool != null(이 두 번째 부분은 유용 하므로 불필요한 것은 아닙니다)
Flater

2
nullableBool == true래퍼를 만들지 않으면 사용하기 시작했습니다 . == true@Flater가 언급했듯이 일반 부울을 사용할 때 일반적으로 쓰지 않기 때문에 읽을 수 있으므로 변수가 nullable임을 제안합니다. 또한 @Fabio에서 언급 한 것처럼 여러 null 조건을 사용하지 않기 때문에 LINQ 가독성이 향상됩니다.
Santhos

답변:


4

이 특정한 경우에, 따라하는 것이 현명 수 있습니다 데메테르의 법칙 , 즉

public class Team
{
    public bool IsManagerVietnamVet => Manager?.IsVietnamVet ?? false;
}    

더 일반적으로 부울 표현식이 복잡하거나 못생긴 경우 별도의 문장으로 나눌 수 없다는 말은 없습니다.

bool isVietnamVet = Manager?.IsVietnamVet ?? false;

if (team.Category == "A Team" && isVietnamVet)

디버거에서 코드를 단계별로 실행할 때 bool약간의 마우스 오버 호버링을 저장하기 위해 정교한 조건을 단일 패키지로 묶는 것이 더 좋습니다 . 사실, 모든 것을 bool변수 에 넣는 것이 더 좋을 수도 있습니다 .

bool isVietnamVetAndCategoryA = (team.Category == "A Team"
    && Manager?.IsVietnamVet ?? false);

if (isVietnamVetAndCategoryA)

또는 LINQ와 함께 :

var wibble = from flight in airport
             from passenger in flight.manifest
             let isOnPlane = 
                 (flight.FinishedBoarding && passenger.Flight == flight.FlightNumber)
             where !isOnPlane
             select passenger;

나는 주로 그러한 해결책에 기울고 있다고 생각합니다.
Santhos

1
몇 줄을 저장하는 새로운 C # 구문 : public bool IsManagerVietnamVet => (team.Category == "") && (team.Manager? .IsVietnamVet ?? false);
Graham

long a && b && c &&...은 순차적으로 실행되며, 이전이이면 다음은 실행되지 않습니다 false. 그래서 사람들은 보통 처음에 가장 빨리 씁니다. 별도의 부울-VAR에 물건을 이동할 때 마음에 계속
jitbit

@jitbit 유지 보수성에 대한 자세한 내용입니다. 언급 한 것과 같은 미세 최적화는 일반적으로 불필요합니다. 성능이 문제로 식별되고 프로파일 링을 통해 그러한 변경이 눈에 띄는 영향을 미치지 않는다면 걱정할 필요가 없습니다.
벤 Cottrell

@BenCottrell 나는 IsManagerVietnamVet속성이 데이터베이스를 체크 인하 면 "마이크로"최적화라고 부를 것이다 ;)
jitbit

3

나는 옵션 3 (즉, == true)이 그것이 무엇인지에 대해 매우 명확하기 때문에 a bool?true무엇인지 테스트하는 가장 깨끗한 방법 이라고 생각 합니다.

대부분의 코드 x == true는와 동일하기 때문에 의미 x가 없지만 여기에는 적용되지 않으므로 == true매우 혼란스럽지 않습니다.


1
Linq 안전하기 때문에 null 조건부 연산자를 사용하려는 경우 이것이 반드시 갈 길이라고 생각합니다. 문제는 가독성이 좋은지 여부입니다. 내 관점에서 볼 때 선택은 opt 3과 opt 4 사이이며 가독성을 위해 4를 3 이상으로 선택하고 프로그래머의 의도도 좀 더 명확 해 보입니다. Ben Cottrell의 대답이 올바른 것으로 표시했습니다. 두 가지 답변을 표시 할 수 있다면 그렇게 할 것입니다.
Santhos

1
@Santhos- "프로그래머의 의도는 좀 더 분명해 보인다" IMHO, 이것은 프로그래머가 처음으로 a?.b == true혼란스러워하는 것을 보는 경우이지만, 일단 그들이하는 일을 파악 != null하면 복잡한 표현의 중간에 테스트하는 것보다 훨씬 읽기 쉬운 관용구가됩니다 . 위해 같은 a?.b ?? false당신이 유형을 취급 한 경우 사용자가 입력하는 것이 무엇 일치하기 때문에, 가장 인기있는 솔루션으로 견인을 얻은 것으로 보인다, 다른 [부울보다는 내가 부울 그것을 싫어하지만, 저에게는 자연스럽게 읽히지 않습니다. 선호합니다 == true].
ToolmakerSteve

3

Ben Cottrell의 답변을 확장하면 "Null Object"패턴이 도움이 될 수 있습니다.

null팀 / 매니저 를 반환하는 대신 추출 ITeamIManager인터페이스를 추출 하고 의미있는 대체 구현을 반환하십시오.

public class NoManager : IManager
{
    public bool IsVietnamVet => false;
}

public class NoTeam : ITeam
{
    public bool ManagedByVietnamVet => false;

    public IManager Manager => new NoManager();
}

그러면 갑자기 team.ManagedByVietnamVet안전하게 할 수 있습니다 .

물론 이것은 업스트림 공급자 team가 null 안전을 요구하지만 적절한 테스트를 통해 보장 할 수 있습니다.


-4

나는 당신이 사용할 수있는 간단한 수업을 썼습니다 :

 public class MyBool 
    {
        public bool? Value { get; set; }

        public MyBool(bool b)
        {
            Value = b;
        }

        public MyBool(bool? b)
        {
            Value = b;
        }

        public static implicit operator bool(MyBool m)
        {
            return m?.Value ?? false;
        }

        public static implicit operator bool?(MyBool m)
        {
            return m?.Value;
        }

        public static implicit operator MyBool(bool m)
        {
            return new MyBool(m);
        }

        public static implicit operator MyBool(bool? m)
        {
            return new MyBool(m);
        }

        public override string ToString()
        {
            return Value.ToString();
        }
    }

물론 사용자 정의 유형을 사용하는 것이 안정적이라면. 당신은 비교할 수 MyBool모두 boolNullable<bool>.


1
이 사이트는 특정 코드 조각을 작동시키는 방법보다는 소프트웨어 디자인에 대한 질문을위한 것이므로 이것이 최상의 솔루션 이라고 생각하는 경우 이와 같은 클래스가 최상의 솔루션이라고 생각하는 이유에 초점을 맞추어야 합니다. 그것을 구현하는 데 필요한 정확한 코드.
Ixrec
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.