이 코드 줄을 가로 질러 달려보십시오.
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
두 개의 물음표는 어떤 의미입니까, 어떤 종류의 삼항 연산자입니까? Google에서 찾기가 어렵습니다.
이 코드 줄을 가로 질러 달려보십시오.
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
두 개의 물음표는 어떤 의미입니까, 어떤 종류의 삼항 연산자입니까? Google에서 찾기가 어렵습니다.
답변:
그것은 합체 연산자이며, 삼항 (즉시) 연산자와 매우 비슷합니다. 또한보십시오 ?? 운영자-MSDN .
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
로 확장 :
FormsAuth = formsAuth != null ? formsAuth : new FormsAuthenticationWrapper();
다음으로 확장됩니다.
if(formsAuth != null)
FormsAuth = formsAuth;
else
FormsAuth = new FormsAuthenticationWrapper();
영어로, "왼쪽에있는 것이 널이 아닌 경우이를 사용하고 그렇지 않으면 오른쪽에있는 것을 사용하십시오"를 의미합니다.
이 중 몇 가지를 순서대로 사용할 수 있습니다. 다음 명령문은 널 Answer#
이 아닌 첫 번째를 지정합니다 Answer
(모든 응답이 널인 경우에는 Answer
널임).
string Answer = Answer1 ?? Answer2 ?? Answer3 ?? Answer4;
또한 위의 확장은 개념적으로 동일하지만 각 식의 결과는 한 번만 평가됩니다. 예를 들어 표현식이 부작용이있는 메소드 호출 인 경우에 중요합니다. (이 점을 지적한 @Joey에게 감사의 뜻을 전합니다.)
??
는 연관되어 있으므로 a ?? b ?? c ?? d
와 같습니다 ((a ?? b) ?? c ) ?? d
. "할당 연산자와 삼항 연산자 (? :)는 오른쪽 연관입니다. 다른 모든 이진 연산자는 연관되어 있습니다." 출처 : msdn.microsoft.com/en-us/library/ms173145.aspx
아무도 마법의 단어를 아직 말하지 않았기 때문에 그것은 null 통합 연산자 입니다. C # 3.0 언어 사양 의 섹션 7.12에 정의되어 있습니다 .
특히 표현식에서 여러 번 사용될 때 작동하는 방식 때문에 매우 편리합니다. 형식의 표현 :
a ?? b ?? c ?? d
a
null이 아닌 경우 expression의 결과를 제공하고 b
, 그렇지 않으면 try c
, 그렇지 않으면 try을 제공 d
합니다. 모든 지점에서 단락됩니다.
또한의 유형이 d
널 입력 가능하지 않은 경우 전체 표현식의 유형도 널 입력 가능하지 않습니다.
Null 통합 연산자입니다.
http://msdn.microsoft.com/en-us/library/ms173224.aspx
네, 그것이 무엇인지 알지 않는 한 검색이 거의 불가능합니다! :-)
편집 : 그리고 이것은 다른 질문에서 멋진 기능입니다. 당신은 그들을 연결할 수 있습니다.
모두들 감사합니다. MSDN 사이트에서 가장 간결한 설명은 다음과 같습니다.
// y = x, unless x is null, in which case y = -1.
int y = x ?? -1;
-1
일반입니다 int
).
x
유형이다 int?
, 그러나 y
유형이다 int
, 당신은 쓸 수 있습니다 int y = (int)(x ?? -1)
. 그것은 구문 분석 x
에 int
그렇지 않은 경우 null
, 또는 지정 -1
을 y
하는 경우 x
입니다 null
.
두 개의 물음표 (??)는 해당 Coalescing 연산자를 나타냅니다.
Coalescing 연산자는 체인에서 첫 번째 NON-NULL 값을 반환합니다. 실제로 모든 것을 보여주는 이 YouTube 비디오 를 볼 수 있습니다 .
그러나 비디오의 내용을 더 추가하겠습니다.
통합의 영어 의미를 보면 "함께 통합"이라고 말합니다. 예를 들어 아래는 4 개의 문자열을 연결하는 간단한 통합 코드입니다.
그래서 경우는 str1
이다 null
그것을 시도 할 str2
경우 str2
입니다 null
그것은 시도 할 것이다 str3
그래서이 null이 아닌 값을 가진 문자열을 찾을 때까지합니다.
string final = str1 ?? str2 ?? str3 ?? str4;
간단히 말해 Coalescing 연산자는 체인에서 첫 번째 NON-NULL 값을 반환합니다.
삼항 연산자의 짧은 손입니다.
FormsAuth = (formsAuth != null) ? formsAuth : new FormsAuthenticationWrapper();
또는 삼항을하지 않는 사람들을 위해 :
if (formsAuth != null)
{
FormsAuth = formsAuth;
}
else
{
FormsAuth = new FormsAuthenticationWrapper();
}
!= null
)와 두 번째 formsAuth
(이후 ?
)를 변경할 수 있습니다. 널 통합 양식에서, 둘 다 제공 한 값을 내재적으로 가져옵니다.
Ruby에 익숙하다면 ||=
C #과 비슷합니다 ??
. 다음은 루비입니다.
irb(main):001:0> str1 = nil
=> nil
irb(main):002:0> str1 ||= "new value"
=> "new value"
irb(main):003:0> str2 = "old value"
=> "old value"
irb(main):004:0> str2 ||= "another new value"
=> "old value"
irb(main):005:0> str1
=> "new value"
irb(main):006:0> str2
=> "old value"
그리고 C #에서 :
string str1 = null;
str1 = str1 ?? "new value";
string str2 = "old value";
str2 = str2 ?? "another new value";
x ||= y
desugars와 같은 것으로 x = x || y
, ??
실제로 ||
Ruby의 일반과 비슷합니다 .
??
만 걱정이 약 null
의 반면 ||
대부분의 언어에서와 루비의 연산자보다 약 null
, false
의 값을 부울 고려 될 수있다, 또는 아무것도 false
(일부 언어의 예는, ""
). 이것은 좋고 나쁜 것이 아니라 단지 차이입니다.
이것에 대해 위험한 것은 없습니다. 사실, 그것은 아름답습니다. 원하는 경우 기본값을 추가 할 수 있습니다 (예 :
암호
int x = x1 ?? x2 ?? x3 ?? x4 ?? 0;
int? x1 = null;
맞습니까
x1
- x4
nullable 형식이어야한다 : 효과적으로, "결과가 말을 할 의미하지 않습니다 0
경우 x4
(이것은 아마도 취할 수없는 값입니다" null
). 여기서 "널링 가능 유형"에는 물론 널 입력 가능 값 유형과 참조 유형이 모두 포함됩니다 . 하나 이상의 연결 변수 (마지막 변수 제외)가 널 입력 가능하지 않은 경우 컴파일 타임 오류입니다.
"널 병합 연산자"( ?? ) 라는 수많은 답변에서 올바르게 지적했듯이 , "널 조건 연산자"( ?. 또는 ? [ ) 의 사촌을 확인하고 싶을 수도 있습니다 . 여러 번 사용하면 ??
멤버 액세스 ( ?. ) 또는 인덱스 ( ? [ ) 조작을 수행하기 전에 널을 테스트하는 데 사용됩니다 . 이 연산자는 특히 데이터 구조로 내림차순으로 null 검사를 처리하는 코드를 적게 작성하도록 도와줍니다.
예를 들면 다음과 같습니다.
// if 'customers' or 'Order' property or 'Price' property is null,
// dollarAmount will be 0
// otherwise dollarAmount will be equal to 'customers.Order.Price'
int dollarAmount = customers?.Order?.Price ?? 0;
없는 오래된 방법 ?. 그리고 ?? 이것을하는 것의
int dollarAmount = customers != null
&& customers.Order!=null
&& customers.Order.Price!=null
? customers.Order.Price : 0;
더 장황하고 번거 롭습니다.
당신의 즐거움을 위해서만 (당신은 모두 C # 사람임을 알고 있습니다 ;-).
스몰 토크 (Smalltalk)에서 유래 한 것으로 생각되며 수년 동안 존재 해 왔습니다. 여기에는 다음과 같이 정의됩니다.
객체에서 :
? anArgument
^ self
UndefinedObject (일명 nil 클래스)에서 :
? anArgument
^ anArgument
이것에 대한 평가 (?) 및 비평가 버전 (??)이 모두 있습니다.
게으른 초기화 개인 (인스턴스) 변수에 대한 getter-methods에서 종종 발견되며 실제로 필요할 때까지 0으로 남아 있습니다.
여기서 병합을 사용하여 값을 얻는 몇 가지 예는 비효율적입니다.
당신이 정말로 원하는 것은 :
return _formsAuthWrapper = _formsAuthWrapper ?? new FormsAuthenticationWrapper();
또는
return _formsAuthWrapper ?? (_formsAuthWrapper = new FormsAuthenticationWrapper());
이렇게하면 매번 개체가 다시 만들어지지 않습니다. 개인 변수가 널로 남아 있고 모든 요청에서 새 오브젝트가 작성되는 대신 새 오브젝트가 작성되면 개인 변수가 지정됩니다.
??
평가 되지 않습니까? nil 인 경우에만new FormsAuthenticationWrapper();
평가 됩니다 _formsAuthWrapper
.
나는이 스레드와 다른 많은 것들을 읽었지만 이만큼 완전한 대답을 찾을 수는 없습니다.
"사용해야하는 이유 및 사용시기 ?? 및 사용 방법 ??"를 완전히 이해했습니다.
Craig McMurtry의 ISBN 0-672-32948-4
값이 값 유형의 인스턴스에 지정되었는지 여부를 알고 싶은 두 가지 일반적인 상황이 있습니다. 첫 번째는 인스턴스가 데이터베이스의 값을 나타내는 경우입니다. 이 경우 인스턴스가 데이터베이스에 실제로 값이 있는지 확인하기 위해 인스턴스를 검사 할 수 있기를 원합니다. 이 책의 주제와 관련이있는 다른 상황은 인스턴스가 일부 원격 소스에서 수신 한 데이터 항목을 나타내는 경우입니다. 다시, 인스턴스로부터 그 데이터 아이템에 대한 값이 수신되었는지를 결정하고자한다.
.NET Framework 2.0에는 값 형식의 인스턴스에 null을 할당하고 인스턴스 값이 null인지 테스트하려는 경우와 같은 경우를 제공하는 일반 형식 정의가 통합되어 있습니다. 이 제네릭 형식 정의는 System.Nullable이며 T를 값 형식으로 대체 할 수있는 제네릭 형식 인수를 제한합니다. System.Nullable에서 생성 된 유형의 인스턴스에는 null 값을 할당 할 수 있습니다. 실제로 해당 값은 기본적으로 null입니다. 따라서 System.Nullable에서 생성 된 형식은 Null 허용 값 형식이라고 할 수 있습니다. System.Nullable에는 인스턴스 값이 null이 아닌 경우 해당 형식으로 구성된 형식의 인스턴스에 할당 된 값을 얻을 수있는 속성 Value가 있습니다. 따라서 다음과 같이 작성할 수 있습니다.
System.Nullable<int> myNullableInteger = null;
myNullableInteger = 1;
if (myNullableInteger != null)
{
Console.WriteLine(myNullableInteger.Value);
}
C # 프로그래밍 언어는 System.Nullable에서 생성 된 형식을 선언하기위한 약식 구문을 제공합니다. 이 구문을 사용하면 다음과 같은 약어를 사용할 수 있습니다.
System.Nullable<int> myNullableInteger;
에
int? myNullableInteger;
컴파일러는 다음과 같이 널 입력 가능 값 유형의 값을 일반 값 유형에 지정하지 못하게합니다.
int? myNullableInteger = null;
int myInteger = myNullableInteger;
널 입력 가능 값 유형에 널 (NULL) 값이있을 수 있으므로 실제로는이 값을 가질 수 있으며 해당 값을 일반 값 유형에 지정할 수 없기 때문에이를 수행하지 못하게합니다. 컴파일러는이 코드를 허용하지만
int? myNullableInteger = null;
int myInteger = myNullableInteger.Value;
System.Nullable에서 생성 된 형식에 유효한 T 값이 할당되지 않은 경우 System.Nullable.Value 속성에 액세스하려는 시도가 잘못된 작업이므로 두 번째 문에서 예외가 발생합니다. 케이스.
nullable 값 형식의 값을 일반 값 형식에 할당하는 올바른 방법 중 하나는 System.Nullable.HasValue 속성을 사용하여 유효한 T 값이 nullable 값 형식에 할당되었는지 확인하는 것입니다.
int? myNullableInteger = null;
if (myNullableInteger.HasValue)
{
int myInteger = myNullableInteger.Value;
}
다른 옵션은이 구문을 사용하는 것입니다.
int? myNullableInteger = null;
int myInteger = myNullableInteger ?? -1;
일반 정수 myInteger에 널 (NULL) 입력 가능 정수 "myNullableInteger"의 값이 지정됩니다. 그렇지 않으면 myInteger에 값 -1이 할당됩니다.
삼항 연산자와 비슷하게 작동하는 null 병합 연산자입니다.
a ?? b => a !=null ? a : b
이것에 대한 또 다른 흥미로운 점은 "널링 가능 유형은 값을 포함하거나 정의 할 수 없음" 입니다. 따라서 널 입력 가능 값 유형을 널 입력 불가능 값 유형에 지정하려고하면 컴파일시 오류가 발생합니다.
int? x = null; // x is nullable value type
int z = 0; // z is non-nullable value type
z = x; // compile error will be there.
그래서 그것을 사용하여 ?? 운영자:
z = x ?? 1; // with ?? operator there are no issues
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
에 해당
FormsAuth = formsAuth != null ? formsAuth : new FormsAuthenticationWrapper();
그러나 멋진 점은 다른 사람들이 말했듯이 체인을 묶을 수 있다는 것입니다. 손대지 않은 것은 실제로 예외를 사용하는 데 사용할 수 있다는 것입니다.
A = A ?? B ?? throw new Exception("A and B are both NULL");
이 ??
연산자를 널 병합 연산자라고합니다. 피연산자가 널이 아닌 경우 왼쪽 피연산자를 리턴합니다. 그렇지 않으면 오른쪽 피연산자를 반환합니다.
int? variable1 = null;
int variable2 = variable1 ?? 100;
NOT NULL 이면 variable2
값으로 설정하십시오 . 그렇지 않으면 인 경우 100으로 설정하십시오 .variable1
variable1
variable1 == null
variable2