Null 병합 연산자를 사용하여 Null 개체 인스턴스화


12

다음과 같은 일반적인 시나리오를 고려하십시오.

if(myObject == null) {
    myObject = new myClass();
}

null-coalescing 연산자를 사용하여 다음 교체에 대해 어떻게 생각하는지 궁금합니다.

myObject = myObject ?? new myClass();

두 번째 양식을 사용해야하는지 잘 모르겠습니다. 좋은 속기 myObject = myObject처럼 보이지만 처음 에는 구문이 약간 코드 냄새가 나는 것처럼 보입니다.

이것이 합리적인 일입니까, 아니면 내가 빠진 것이 더 나은 속기입니까? 아니면 "3 줄이야, 극복 해!"

편집 : 언급했듯이, 이것을 전형적인 시나리오라고 부르는 것은 과장된 것입니다. 일반적으로 아직 채워지거나 채워지지 않은 자식 참조 유형 속성이있는 데이터베이스에서 엔티티를 검색 할 때이 상황이 발생한다는 것을 알았습니다.

myClass myObject = myClassService.getById(id);
myObject.myChildObject = myObject.myChildObject ?? new myChildClass();

15
초보자들은 이와 같은 것들이 "hackish"라고 믿고, 더 숙련 된 개발자들은 이것을 "아이디 오 매틱"이라고 부릅니다.
Doc Brown

객체가 가치 객체처럼 보이는 경우 (관용적 표현에서 "값 의미론을 가짐") 해당 유형 의 값 멤버를 MyClass제공해야합니다 . MSDN을 참조하십시오 . public static readonlyEmptyString.Empty
rwong


5
이없는 ??=운전자는?
aviv

1
@ aviv 나는 거기 있었으면 좋겠다!
Loren Pechtel

답변:


16

항상 null 병합 연산자를 사용합니다. 나는 간결함을 좋아한다.

이 연산자는 본질적으로 삼항 연산자 (A? B : C)와 비슷합니다. 읽는 것이 제 2의 성격이기 전에 약간의 연습이 필요하지만 일단 익숙해지면 긴 버전에 비해 가독성이 향상된다고 생각합니다.

또한 설명하는 상황은 운영자가 유용한 하나의 시나리오 일뿐입니다. 다음과 같은 구문을 바꾸는 것도 편리합니다.

if (value != null)
{
    return value;
}
else
{ 
    return otherValue;
}

또는

return value != null ? value : otherValue;

return value ?? otherValue;

이 연산자 사용에 대해 일반적으로 동의합니다. 그래도 그것을 사용하는 것에 대한 참조를 볼 때 일반적으로 다음과 같습니다 myObject = myObject2 ?? myObject3. 내가 특별히 궁금해하는 것은 null이 아닌 한 연산자를 사용하여 객체를 자체로 설정하는 것입니다.
grin0048

2
두 경우 모두 동일한 추론이 적용된다고 생각합니다. 동일한 논리를 표현하는 더 간결한 방법입니다.
17 26

이 세 가지 형태 각각에 대해 IL을 한 번 본 것을 기억합니다. 첫 번째와 두 번째는 동일하지만 세 번째는 null비교 라고 가정 할 수있는 방식으로 최적화되었습니다 .
Jesse C. Slicer

2

내가 특별히 궁금한 것은 연산자가 null이 아닌 한 객체를 스스로 설정하는 것입니다.

?? operatornull-coalescing 연산자라고하며 nullable 값 형식 또는 참조 형식의 기본값을 정의하는 데 사용됩니다. 피연산자가 널이 아닌 경우 왼쪽 피연산자를 리턴합니다. 그렇지 않으면 올바른 피연산자를 반환합니다.

myObject = myObject ?? new myObject(); - instantiate default value of object

- 널 병합 연산자에 대한 자세한 내용 및 코드 예제 MSDN 문서 .

more than nullable상태 를 확인 하는 경우 대안으로 Ternary 연산자를 사용할 수 있습니다.

삼항 연산자

? : Operator를 볼 수도 있습니다 . 이를 3 차 또는 조건부 연산자 라고 합니다. 조건부 연산자 (? :)는 부울 식의 값에 따라 두 값 중 하나를 반환합니다.

널 입력 가능 유형은 값을 포함하거나 정의되지 않을 수 있습니다. ?? 연산자는 널 입력 가능 유형이 널 입력 불가능 유형에 지정 될 때 리턴 될 기본값을 정의합니다. ??를 사용하지 않고 nullable 값 형식을 nullable 값 형식에 할당하려고하면 연산자를 사용하면 컴파일 타임 오류가 발생합니다. 캐스트를 사용하고 널 입력 가능 값 유형이 현재 정의되어 있지 않으면 InvalidOperationException 예외가 발생합니다.

MSDN 의 코드 예제 -? : Operator (C # Reference) :

int? input = Convert.ToInt32(Console.ReadLine());
string classify;

// ?: conditional operator.
classify = (input.HasValue) ? ((input < 0) ? "negative" : "positive") : "undefined";

따라서 질문에서 예를 들어 조건부 연산자를 적용하면 다음과 같은 결과가 나타납니다 myObject = (myObject == null) ? new myClass() : myObject. 따라서 조건부 연산자를 더 잘 사용하지 않는 한 개체를 null 병합 연산자와 동일하게 설정하는 것과 같은 "문제"가있는 것 같습니다. 간결하지는 않습니다.
grin0048

둘 이상의 조건 ​​(널 (null)이 아니고 0보다 큰)을 확인하는 경우 조건부 연산자가 조건을 수행합니다. 그러나 null 검사 만 작동합니까 ?? 운영자.
Yusubov

2

시나리오가 일반적이라고 생각하지 않습니다.

일부 필드의 기본값이 아닌 null경우 필드 초기화 프로그램에서 설정하십시오.

myClass myObject = new myClass();

또는 초기화가 더 복잡한 경우 생성자에서 설정하십시오.

myClass실제로 필요할 때만 만들려면 (예 : 시간이 오래 걸리는 경우) 다음을 사용할 수 있습니다 Lazy<T>.

Lazy<myClass> myObject = new Lazy<myClass>();

(이것은 기본 생성자를 호출합니다. 초기화가 더 복잡한 myClass경우 Lazy<T>생성자에 생성 되는 람다를 전달 하십시오 .)

값에 액세스하려면을 사용 myObject.Value하십시오. 처음 액세스하는 경우 초기화를 호출합니다 myObject.Value.


IMO 게으른 생성은 결과 객체가 필요하지 않다고 보장되는 경우에만 유용합니다. 게으른 생성을 사용하는 경우에만 변경 사항이있을 때 재설정하는 현금 파생 결과가 있고 동일한 결과가 많이 필요하다는 것을 알고 있습니다 그리고 recalc는 비싸다. 다른 현명한 난 그냥 널 확인 귀찮게하고 싶지 않아
래칫 괴물

@ratchetfreak 그렇습니다. 그래서 필드 초기화를 먼저 제안했습니다.
svick

다른 경우도 있습니다. 내가 지금보고있는 것 : 첫 번째 패스는 예외 경우를 설정합니다. 두 번째 패스는 다른 모든 것에 대한 기본값을 설정합니다. ?? = 줄을 반으로 자릅니다.
Loren Pechtel

1

나는 특히 ??선택적 메소드 매개 변수와 함께 사용하는 것을 좋아 합니다. 과부하의 필요성을 제한하고 그 가치가 있는지 확인합니다.

public void DoSomething (MyClass thing1 = null) {
    thing1 = thing1 ?? new MyClass();
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.