true
문자열 유형이 아니기 때문에 null + true
문자열은 어떻습니까?
string s = true; //Cannot implicitly convert type 'bool' to 'string'
bool b = null + true; //Cannot implicitly convert type 'string' to 'bool'
그 이유는 무엇입니까?
true
문자열 유형이 아니기 때문에 null + true
문자열은 어떻습니까?
string s = true; //Cannot implicitly convert type 'bool' to 'string'
bool b = null + true; //Cannot implicitly convert type 'string' to 'bool'
그 이유는 무엇입니까?
답변:
이상하게 보일지 모르지만 단순히 C # 언어 사양의 규칙을 따르는 것입니다.
섹션 7.3.4에서 :
x op y 형식의 연산은 다음과 같이 처리됩니다. 여기서 op는 오버로드 가능한 이항 연산자, x는 X 유형의 표현식, y는 Y 유형의 표현식입니다.
- 연산 연산자 op (x, y)에 대해 X 및 Y에 의해 제공되는 후보 사용자 정의 연산자 집합이 결정됩니다. 집합은 X가 제공하는 후보 연산자와 Y가 제공하는 후보 연산자의 합집합으로 구성되며, 각각 §7.3.5의 규칙을 사용하여 결정됩니다. X와 Y가 동일한 유형이거나 X와 Y가 공통 기본 유형에서 파생 된 경우 공유 후보 연산자는 결합 된 집합에서 한 번만 발생합니다.
- 후보 사용자 정의 연산자 집합이 비어 있지 않으면이 연산자가 작업에 대한 후보 연산자 집합이됩니다. 그렇지 않으면 해제 된 형식을 포함하여 미리 정의 된 이항 연산자 op 구현이 작업에 대한 후보 연산자 집합이됩니다. 지정된 연산자의 미리 정의 된 구현은 연산자 설명에 지정되어 있습니다 (§7.8 ~ §7.12).
- §7.5.3의 오버로드 해결 규칙은 인수 목록 (x, y)과 관련하여 최상의 연산자를 선택하기 위해 후보 연산자 집합에 적용되며이 연산자는 오버로드 해결 프로세스의 결과가됩니다. 과부하 해결이 단일 최상의 연산자를 선택하지 못하면 바인딩 시간 오류가 발생합니다.
자, 이것을 차례로 살펴 보겠습니다.
X는 여기서 null 유형입니다. 그런 식으로 생각하고 싶다면 유형이 아닙니다. 후보자를 제공하지 않습니다. Y는bool
사용자 정의 +
연산자를 제공하지 않는 입니다. 따라서 첫 번째 단계에서는 사용자 정의 연산자를 찾지 않습니다.
그런 다음 컴파일러는 두 번째 글 머리 기호로 이동하여 미리 정의 된 이항 연산자 + 구현 및 해제 된 형식을 살펴 봅니다. 사양의 섹션 7.8.4에 나열되어 있습니다.
사전 정의 된 연산자를 살펴보면 적용 가능한 유일한 연산자 는 string operator +(string x, object y)
. 따라서 후보 세트에는 단일 항목이 있습니다. 따라서 최종 글 머리 기호가 매우 간단 해집니다. 과부하 해결은 해당 연산자를 선택하여 전체 표현식 유형을string
.
한 가지 흥미로운 점은 언급되지 않은 유형에서 사용할 수있는 다른 사용자 정의 연산자가 있더라도 이것이 발생한다는 것입니다. 예를 들면 :
// Foo defined Foo operator+(Foo foo, bool b)
Foo f = null;
Foo g = f + true;
괜찮지 만 컴파일러가를 찾는 것을 모르기 때문에 null 리터럴에는 사용되지 않습니다 Foo
. string
사양에 명시 적으로 나열된 사전 정의 된 연산자이기 때문에 고려하는 것만 알고 있습니다. (사실, 이것은 문자열 유형으로 정의 된 연산자 가 아닙니다 ... 1 ) 이것은 컴파일에 실패한다는 것을 의미합니다 :
// Error: Cannot implicitly convert type 'string' to 'Foo'
Foo f = null + true;
다른 두 번째 피연산자 유형은 물론 다른 연산자를 사용합니다.
var x = null + 0; // x is Nullable<int>
var y = null + 0L; // y is Nullable<long>
var z = null + DayOfWeek.Sunday; // z is Nullable<DayOfWeek>
1 왜 문자열 + 연산자가 없는지 궁금 할 것 입니다. 합리적인 질문이고 답을 추측 하고 있지만 다음 표현을 고려하십시오.
string x = a + b + c + d;
경우 string
C # 컴파일러에는 특수 케이스가 없었다,이 효율적으로 끝낼 것입니다 :
string tmp0 = (a + b);
string tmp1 = tmp0 + c;
string x = tmp1 + d;
두 개의 불필요한 중간 문자열이 만들어졌습니다. 그러나 컴파일러 내에 특별한 지원이 있기 때문에 실제로 위의 내용을 다음과 같이 컴파일 할 수 있습니다.
string x = string.Concat(a, b, c, d);
정확히 올바른 길이의 단일 문자열을 생성하여 모든 데이터를 정확히 한 번 복사 할 수 있습니다. 좋은.
true
으로 변환되지 않는 string
. 표현식이 유효하면 유형은 string
이지만이 경우 문자열로 변환하지 못하면 전체 표현식이 오류가되므로 유형이 없습니다.
x
유형 string
입니다. 여기에 사용 된 string operator+(string, object)
서명은 bool
으로 변환 object
되지 않고 (괜찮습니다) 로 변환 됩니다 string
.
그 이유는 일단 소개 +
하면 C # 연산자 바인딩 규칙이 적용 되기 때문 입니다. +
사용 가능한 연산자 집합을 고려 하고 최상의 과부하를 선택합니다. 그 연산자 중 하나는 다음과 같습니다.
string operator +(string x, object y)
이 오버로드는 식의 인수 유형과 호환됩니다 null + true
. 따라서 연산자로 선택되고 본질적으로 ((string)null) + true
값을 평가하는 것으로 평가됩니다 "True"
.
C # 언어 사양의 섹션 7.7.4에는이 해결 방법에 대한 세부 정보가 포함되어 있습니다.
operator+
에 대한 string
. 대신 컴파일러의 마음 속에 만 존재하며 단순히 다음을위한 호출로 변환합니다.string.Concat
컴파일러는 먼저 null 인수를받을 수있는 operator + ()를 찾습니다. 표준 값 유형 중 어느 것도 규정하지 않습니다. null은 유효한 값이 아닙니다. 유일한 일치는 System.String.operator + ()이며 모호성이 없습니다.
해당 연산자의 두 번째 인수도 문자열입니다. 그것은 kapooey로 가고, bool을 문자열로 암시 적으로 변환 할 수 없습니다.
흥미롭게도 Reflector를 사용하여 생성 된 내용을 검사하면 다음 코드가 있습니다.
string b = null + true;
Console.WriteLine(b);
컴파일러에 의해 다음과 같이 변환됩니다.
Console.WriteLine(true);
이 "최적화"뒤에있는 이유는 내가 말해야 할 약간 이상하고 내가 기대하는 연산자 선택과 일치하지 않습니다.
또한 다음 코드 :
var b = null + true;
var sb = new StringBuilder(b);
로 변형됩니다
string b = true;
StringBuilder sb = new StringBuilder(b);
string b = true;
실제로 컴파일러에서 허용되지 않는 곳 입니다.
null
null 문자열로 캐스트되고 bool에서 문자열로의 암시 적 변환기가 있으므로는 문자열 true
로 캐스트되고 +
연산자가 적용됩니다. 다음과 같습니다. string str = ""+ true.ToString ();
Ildasm으로 확인하면 :
string str = null + true;
다음과 같습니다.
.locals init ([0] string str)
IL_0000: nop
IL_0001: ldc.i4.1
IL_0002: box [mscorlib]System.Boolean
IL_0007: call string [mscorlib]System.String::Concat(object)
IL_000c: stloc.0