nullable 형식으로 작동하지 않는 null 조건부 연산자?
나는 C # 6으로 코드를 작성 중이며 이상한 이유로 작동합니다.
var value = objectThatMayBeNull?.property;
그러나 이것은 그렇지 않습니다.
int value = nullableInt?.Value;
작동하지 않는다는 것은 컴파일 오류가 발생한다는 것을 의미 Cannot resolve symbol 'Value'
합니다. null 조건부 연산자 ?.
가 작동하지 않는 이유를 아십니까?
좋아, 나는 약간의 생각과 테스트를했다. 다음과 같은 일이 발생합니다.
int value = nullableInt?.Value;
컴파일 할 때 다음 오류 메시지를 제공합니다.
'int'유형에 'Value'에 대한 정의가 없습니다.
즉 ,를 실제 값 으로 ?
'변환'합니다 . 이것은 사실상 다음과 같습니다.int?
int
int value = nullableInt ?? default(int);
결과는 정수이며 Value
, 분명히 는 없습니다 .
좋아요, 도움이 될까요?
int value = nullableInt?;
아니요, 해당 구문은 허용되지 않습니다.
그럼 어쩌죠? .GetValueOrDefault()
이 경우에는 계속 사용 하십시오.
int value = nullableInt.GetValueOrDefault();
그 이유는 null 조건부 연산자로 값에 액세스하는 것이 무의미하기 때문입니다.
- nullable이 아닌 값 유형 인
x?.p
곳에 적용 하면 결과는 유형 입니다. 동일한 토큰으로 작업 결과는 nullable 이어야 합니다.p
T
T?
nullableInt?.Value
- 당신이 때
Nullable<T>
값을 가지고, 결과는nullableInt?.Value
값 자체와 동일한 것 - 당신이 때
Nullable<T>
값이없는, 결과는 것null
, 다시 값 자체와 동일하다.
연산자 를 사용하여 액세스 Value
하는 것은 의미가 없지만 ?.
nullable 값 형식의 다른 속성에 액세스하는 것은 의미가 있습니다. 연산자는 nullable 값 형식 및 참조 형식과 일관되게 작동하므로 다음 두 구현은 동일한 동작을 생성합니다.
class PointClass {
public int X { get; }
public int Y { get; }
public PointClass(int x, int y) { X = x; Y = y; }
}
struct PointStruct {
public int X { get; }
public int Y { get; }
public PointStruct(int x, int y) { X = x; Y = y; }
}
...
PointClass pc = ...
PointStruct? ps = ...
int? x = pc?.X;
int? y = ps?.Y;
nullable의 struct
경우 연산자를 사용하면 기본 형식의 속성에 액세스 할 수 PointStruct
있으며 참조 형식의 nullable이 아닌 속성에 대해 수행하는 것과 동일한 방식으로 결과에 null 허용 여부를 추가합니다 PointClass
.
nullable 유형과 관련하여 ?.
연산자는 if not null, use the wrapped value
. Null 허용 값이있는 경우 그래서 널 (NULL) 인터넷 용, 8
의 결과가 ?.
될 것입니다 8
포함되지 않은 널 (NULL), 8
. Value
의 속성이 아니기 때문에 int
오류가 발생합니다.
따라서 속성을 Value
올바르게 사용하려는 예는 실패하지만 다음은 작동합니다.
var x = nullableInt?.ToString();
Null 통합 연산자를 고려하십시오 ??
.
var x = nullableInt ?? 0;
여기에서 연산자는라고 말합니다 . if null, return 0, otherwise return the value inside the nullable
이 경우에는 int
. ?.
오퍼레이터는 널의 내용을 추출에 관하여 유사하게 수행된다.
특정 예의 경우 ??
연산자 대신 연산자와 적절한 기본값을 사용해야합니다 ?.
.
나는 기본적으로 다른 답변에 동의합니다. 나는 관찰 된 행동이 어떤 형태의 권위있는 문서에 의해 뒷받침 될 수 있기를 바랐습니다.
어디에서도 C # 6.0 사양을 찾을 수 없기 때문에 (아직 출시 되었습니까?) "문서"에 가장 가까운 것은 2014 년 2 월 3 일에 대한 C # 언어 디자인 노트입니다 . 거기에서 발견 된 정보가 여전히 현재 상황을 반영한다고 가정하면 여기에 관찰 된 행동을 공식적으로 설명하는 관련 부분이 있습니다.
의미 체계는식이 한 번만 평가된다는 점을 제외하고는 삼항 연산자를 null 등식 검사, null 리터럴 및 연산자의 질문이없는 응용 프로그램에 적용하는 것과 같습니다.
e?.m(…) => ((e == null) ? null : e0.m(…)) e?.x => ((e == null) ? null : e0.x) e?.$x => ((e == null) ? null : e0.$x) e?[…] => ((e == null) ? null : e0[…])
Where
e0
is the same ase
, except ife
is of a nullable value type, in which casee0
ise.Value
.
Applying that last rule to:
nullableInt?.Value
... the semantically equivalent expression becomes:
((nullableInt == null) ? null : nullableInt.Value.Value)
Clearly, nullableInt.Value.Value
can't compile, and that's what you observed.
As to why the design decision was made to apply that special rule to nullable types specifically, I think dasblinkenlight
's answer covers that nicely, so I won't repeat it here.
Additionally, I should mention that, even if, hypothetically, we didn't have this special rule for nullable types, and the expression nullableInt?.Value
did compile and behave as you originally thought...
// let's pretend that it actually gets converted to this...
((nullableInt == null) ? null : nullableInt.Value)
still, the following statement from your question would be invalid and produce a compilation error:
int value = nullableInt?.Value; // still would not compile
The reason why it would still not work is because the type of the nullableInt?.Value
expression would be int?
, not int
. So you would need to change the type of the value
variable to int?
.
This is also formally covered in the C# Language Design Notes for Feb 3, 2014:
The type of the result depends on the type
T
of the right hand side of the underlying operator:
- If
T
is (known to be) a reference type, the type of the expression isT
- If
T
is (known to be) a non-nullable value type, the type of the expression isT?
- If
T
is (known to be) a nullable value type, the type of the expression isT
- Otherwise (i.e. if it is not known whether
T
is a reference or value type) the expression is a compile time error.
But if you would then be forced to write the following to make it compile:
int? value = nullableInt?.Value;
... then it seems pretty pointless, and it wouldn't be any different from simply doing:
int? value = nullableInt;
As others have pointed out, in your case, you probably meant to use the null-coalescing operator ??
all along, not the null-conditional operator ?.
.
int
doesn't have a Value
property.
Consider:
var value = obj?.Property
Is equivalent to:
value = obj == null ? null : obj.Property;
That makes no sense with int
and hence not with int?
via ?.
The old GetValueOrDefault()
does though make sense with int?
.
Or for that matter, since ?
has to return something nullable, simply:
int? value = nullableInt;
The null conditional operator also unwraps the nullable variable. So after the "?." operator, the “Value” property is no longer needed.
I wrote a post that goes more into detail on how I came across this. In case you're wondering
http://www.ninjacrab.com/2016/09/11/c-how-the-null-conditional-operator-works-with-nullable-types/
Simply because (based on sstan's answer above)
var value = objectThatMayBeNull?.property;
is evaluated by compiler like
var value = (objectThatMayBeNull == null) ? null : objectThatMayBeNull.property
and
int value = nullableInt?.Value;
like
int value = (nullableInt == null) ? null : nullableInt.Value.Value;
when nullableInt.Value.Value
is Cannot resolve symbol 'Value'
syntax error!
'programing tip' 카테고리의 다른 글
XML 속성을 통해 클래스 이름을 어떻게 바꿀 수 있습니까? (0) | 2020.12.03 |
---|---|
Express js를 출력 파일에 로그인 하시겠습니까? (0) | 2020.12.03 |
.Net Core 및 NuGet (0) | 2020.12.02 |
Visual Studio를 사용하는 GCC? (0) | 2020.12.02 |
기본적으로 display : inline-block? (0) | 2020.12.02 |