Programing

null + true는 어떻게 문자열입니까?

crosscheck 2020. 7. 27. 07:31
반응형

null + true는 어떻게 문자열입니까?


때문에 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)에 지정되어 있습니다.
  • 인수 목록 (x, y)과 관련하여 최상의 연산자를 선택하기 위해 후보 연산자 세트에 §7.5.3의 과부하 해결 규칙이 적용되며이 연산자는 과부하 해결 프로세스의 결과가됩니다. 과부하 해결이 최상의 단일 연산자를 선택하지 못하면 바인딩 시간 오류가 발생합니다.

자, 이것을 차례로 살펴 봅시다.

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;

경우 stringC # 컴파일러에는 특수 케이스가 없었다,이 효율적으로 끝낼 것입니다 :

string tmp0 = (a + b);
string tmp1 = tmp0 + c;
string x = tmp1 + d;

그래서 두 개의 불필요한 중간 문자열이 만들어졌습니다. 그러나 컴파일러 내에서 특별한 지원이 있기 때문에 실제로 위와 같이 컴파일 할 수 있습니다.

string x = string.Concat(a, b, c, d);

모든 길이의 데이터를 정확히 한 번만 복사하여 정확한 길이의 단일 문자열 만 만들 수 있습니다. 좋은.


그 이유는 일단 +C # 연산자 바인딩 규칙 을 도입하면 작동하기 때문 입니다. +사용 가능한 연산자 세트를 고려 하고 최상의 과부하를 선택합니다. 그 연산자 중 하나는 다음과 같습니다

string operator +(string x, object y)

This overload is compatible with the argument types in the expression null + true. Hence it is selected as the operator and is evaluated as essentially ((string)null) + true which evaluates to the value "True".

Section 7.7.4 of the C# language spec contains the details around this resolution .


The compiler goes out hunting for an operator+() that can take a null argument first. None of the standard value types qualify, null is not a valid value for them. The one and only match is System.String.operator+(), there's no ambiguity.

The 2nd argument of that operator is also a string. That goes kapooey, cannot implicitly convert bool to string.


Interestingly, using Reflector to inspect what is generated, the following code:

string b = null + true;
Console.WriteLine(b);

is transformed into this by the compiler:

Console.WriteLine(true);

The reasoning behind this "optimization" is a bit weird I must say, and does not rhyme with the operator selection I would expect.

Also, the following code:

var b = null + true; 
var sb = new StringBuilder(b);

is transformed into

string b = true; 
StringBuilder sb = new StringBuilder(b);

where string b = true; is actually not accepted by the compiler.


null will be cast to null string, and there is implicit converter from bool to string so the true will be cast to string and then, + operator will be applied: it's like: string str = "" + true.ToString();

if you check it with Ildasm:

string str = null + true;

it's as bellow:

.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

var b = (null + DateTime.Now); // String
var b = (null + 1);            // System.Nullable<Int32> | same with System.Single, System.Double, System.Decimal, System.TimeSpan etc
var b = (null + new Object()); // String | same with any ref type

Crazy?? No, there must be a reason behind it.

Someone call Eric Lippert...


The reason for this is convenience (concatenating strings is a common task).

As BoltClock said, the '+' operator is defined on numeric types, strings, and can be defined for our own types as well (operator overloading).

If there is not an overloaded '+' operator on the argument's types and they are not numeric types, the compiler defaults to string concatenation.

The compiler inserts a call to String.Concat(...) when you concatenate using '+', and the implementation of Concat calls ToString on each object passed into it.

참고URL : https://stackoverflow.com/questions/4472900/how-is-null-true-a-string

반응형