[C#] 널 문자열을 연결하는 것이 유효하지만“null.ToString ()”을 호출하지 않는 이유는 무엇입니까?

이것은 유효한 C # 코드입니다

var bob = "abc" + null + null + null + "123";  // abc123

유효한 C # 코드가 아닙니다.

var wtf = null.ToString(); // compiler error

첫 번째 진술이 왜 유효합니까?



답변

첫 번째 이유 :

에서 MSDN :

문자열 연결 작업에서 C # 컴파일러는 null 문자열을 빈 문자열과 동일하게 취급하지만 원래 null 문자열의 값은 변환하지 않습니다.

+ 이항 연산자 에 대한 추가 정보 :

이항 + 연산자는 하나 또는 두 피연산자가 모두 문자열 유형 인 경우 문자열 연결을 수행합니다.

문자열 연결 피연산자가 널이면 빈 문자열이 대체됩니다. 그렇지 않으면, 문자열이 아닌 인수는 ToString유형 객체에서 상속 된 가상 메소드 를 호출하여 문자열 표현으로 변환됩니다 .

ToString반환 null하면 빈 문자열이 대체됩니다.

두 번째 오류의 원인은 다음과 같습니다.

null (C # 참조) -null 키워드는 개체를 참조하지 않는 null 참조를 나타내는 리터럴입니다. 참조 유형 변수의 기본값은 null입니다.


답변

+C # 의 연산자는 내부적으로로 변환 되기 때문에 String.Concat정적 메서드입니다. 그리고이 방법 null은 빈 문자열처럼 취급 됩니다. String.ConcatReflector 의 소스를 보면 다음과 같이 표시됩니다.

// while looping through the parameters
strArray[i] = (str == null) ? Empty : str;
// then concatenate that string array

(MSDN에서도 언급 함 : http://msdn.microsoft.com/en-us/library/k9c94ey1.aspx )

반면에 ToString()인스턴스 메소드는 호출 할 수 없습니다 null(어떤 유형을 사용해야 null합니까?).


답변

번째 샘플 은 다음과 같이 번역됩니다.

var bob = String.Concat("abc123", null, null, null, "abs123");

Concat메소드는 입력을 확인하고 null을 빈 문자열로 변환합니다.

번째 샘플 은 다음과 같이 번역됩니다.

var wtf = ((object)null).ToString();

따라서 null여기에 참조 예외가 생성됩니다


답변

코드의 첫 번째 부분은에서와 같이 취급됩니다 String.Concat.

이것은 문자열을 추가 할 때 C # 컴파일러가 호출하는 것입니다. ” abc" + null로 번역됩니다 String.Concat("abc", null).

내부적으로이 방법은 null로 대체 됩니다 String.Empty. 따라서 코드의 첫 번째 부분에서 예외가 발생하지 않습니다. 그것은 같다

var bob = "abc" + string.Empty + string.Empty + string.Empty + "123";  //abc123

그리고 ‘null’이 객체가 아니기 때문에 코드의 두 번째 부분에서 예외가 발생 합니다 .null 키워드는 객체를 참조하지 않는 null 참조를 나타내는 리터럴입니다 . 참조 유형 변수의 기본값은 null입니다.

그리고 ‘ ToString()‘는 객체의 인스턴스에 의해 호출 될 수 있지만 리터럴은 아닙니다.


답변

.net 이전의 COM 프레임 워크에서는 문자열을 수신 한 루틴이 완료되면이를 해제 할 필요가있었습니다. 빈 문자열이 루틴으로 들어오고 나가는 것이 매우 일반적이기 때문에 널 포인터를 “해제”하려는 시도는 합법적 인 수행 작업으로 정의 되었기 때문에 Microsoft는 널 문자열 포인터가 빈 문자열을 나타내도록 결정했습니다.

COM과의 일부 호환성을 위해 .net의 많은 루틴은 null 개체를 빈 문자열로 유효한 표현으로 해석합니다. .net 및 해당 언어의 약간의 변경 (대부분 인스턴스 멤버가 “가상으로 호출하지 않음”을 표시하도록 허용 함)을 통해 Microsoft null는 선언 된 유형 String의 개체를 빈 문자열처럼 동작하도록 만들 수있었습니다 . 만약 마이크로 소프트가 그렇게했다면, Nullable<T>작업을 다소 다르게 Nullable<String>해야했고 (어쨌든 IMHO가해야 할 일 을 허용하기 위해 ) 그리고 / 또는 NullableString대체로 상호 교환이 가능 String하지만 null유효한 빈 문자열로.

null그대로 a는 합법적 인 빈 문자열로 간주되고 그렇지 않은 컨텍스트 도 있습니다. 매우 유용한 상황은 아니지만 프로그래머가 알아야 할 상황입니다. 일반적으로 is 인 stringValue.someMember경우 양식의 표현식 이 실패 하지만 매개 변수로 문자열을 허용하는 대부분의 프레임 워크 메소드 및 연산자 는 빈 문자열로 간주 됩니다.stringValuenullnull


답변

'+'중위 연산자입니다. 다른 연산자와 마찬가지로 실제로 메서드를 호출합니다. 비-고정 버전을 상상할 수 있습니다"wow".Plus(null) == "wow"

구현자는 이와 같은 것을 결정했습니다 …

class String
{
  ...
  String Plus(ending)
  {
     if(ending == null) return this;
     ...
  }
} 

그래서 .. 당신의 모범은

var bob = "abc".Plus(null).Plus(null).Plus(null).Plus("123");  // abc123

이것은 같은

var bob = "abc".Plus("123");  // abc123

어느 시점에서도 null은 문자열이되지 않습니다. 그렇게 null.ToString()다르지 않습니다 null.VoteMyAnswer(). 😉


답변

객체를 참조하지 않는 리터럴 이기 때문에 추측 합니다. ToString()필요합니다 object.