이것은 유효한 C # 코드입니다
var bob = "abc" + null + null + null + "123"; // abc123
유효한 C # 코드가 아닙니다.
var wtf = null.ToString(); // compiler error
첫 번째 진술이 왜 유효합니까?
class null_extension { String ToString( Object this arg ) { return ToString(arg); } }
이것은 유효한 C # 코드입니다
var bob = "abc" + null + null + null + "123"; // abc123
유효한 C # 코드가 아닙니다.
var wtf = null.ToString(); // compiler error
첫 번째 진술이 왜 유효합니까?
class null_extension { String ToString( Object this arg ) { return ToString(arg); } }
답변:
첫 번째 이유 :
에서 MSDN :
문자열 연결 작업에서 C # 컴파일러는 null 문자열을 빈 문자열과 동일하게 취급하지만 원래 null 문자열의 값은 변환하지 않습니다.
+ 이항 연산자 에 대한 추가 정보 :
이항 + 연산자는 하나 또는 두 피연산자가 모두 문자열 유형 인 경우 문자열 연결을 수행합니다.
문자열 연결 피연산자가 널이면 빈 문자열이 대체됩니다. 그렇지 않으면, 문자열이 아닌 인수는
ToString유형 객체에서 상속 된 가상 메소드 를 호출하여 문자열 표현으로 변환됩니다 .을
ToString반환null하면 빈 문자열이 대체됩니다.
두 번째 오류의 원인은 다음과 같습니다.
null (C # 참조) -null 키워드는 개체를 참조하지 않는 null 참조를 나타내는 리터럴입니다. 참조 유형 변수의 기본값은 null입니다.
wtf = ((String)null).ToString();최근에 null을 캐스팅 할 수있는 Java에서 일하고 있습니다 .C #으로 작업 한 지 오래되었습니다.
null.ToString()vs 로 생각하십시오 ToString(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합니까?).
+C #의 문자열 연산자는 구문 설탕입니다 String.Concat.
__arglist및 params객체 배열 버전입니다.
Concat널이 아닌 문자열의 배열이 주어 졌을 때에도 항상 널이 아닌 문자열의 새 배열을 작성 합니까 ? 아니면 다른 일이 있습니까?
첫 번째 샘플 은 다음과 같이 번역됩니다.
var bob = String.Concat("abc123", null, null, null, "abs123");
이 Concat메소드는 입력을 확인하고 null을 빈 문자열로 변환합니다.
두 번째 샘플 은 다음과 같이 번역됩니다.
var wtf = ((object)null).ToString();
따라서 null여기에 참조 예외가 생성됩니다
AccessViolationException던져 질 것이다 :)
((object)null).ToString()=> AccessViolation ((object)1 as string).ToString()=>NullReference
((object)null).ToString()돌며 try/catch내가 얻을 NullReferenceException너무.
코드의 첫 번째 부분은에서와 같이 취급됩니다 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()'는 객체의 인스턴스에 의해 호출 될 수 있지만 리터럴은 아닙니다.
String.Empty와 같지 않습니다 null. 와 같은 일부 메소드에서 동일한 방식으로 처리되었습니다 String.Concat. 예를 들어, 문자열 변수를로 설정하면 nullC #은 String.Empty메서드를 호출하려고 할 때이를 대체하지 않습니다 .
null는 String.EmptyC #에서 다루지 않고 String.Concat문자열에서 추가 할 때 C # 컴파일러가 호출하는 방식으로 처리됩니다. "abc" + null로 번역됩니다 String.Concat("abc", null), 내부적으로, 그 방법을 대체 null와 String.Empty. 두 번째 부분은 완전히 정확합니다.
.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(). ;)
var bob = Plus(Plus(Plus(Plus("abc",null),null),null),"123");합니다. 연산자 오버로드는 마음에서 정적 방법은 다음과 같습니다 msdn.microsoft.com/en-us/library/s53ehcz3(v=VS.71).aspx는 그들이 아니었다면, var bob = null + "abc";또는 특히 string bob = null + null;유효하지 않을 것입니다.
누군가이 토론 스레드 에서 아무 것도 문자열을 만들 수 없다고 말했습니다 . (내 생각에는 좋은 문구입니다). 그러나 예- 다음 예제와 같이 :-) 할 수 있습니다 .
var x = null + (string)null;
var wtf = x.ToString();
잘 작동하고 전혀 예외를 throw하지 않습니다. 유일한 차이점은 널 중 하나를 문자열로 캐스트해야한다는 것입니다. (문자열) 캐스트 를 제거 하면 예제는 여전히 컴파일되지만 런타임 예외가 발생합니다. "연산자 '+'는 피연산자에 대해 모호합니다. '<null>'및 '<null>' "을 입력하십시오.
NB 위의 코드 예제에서 x의 값은 예상대로 null이 아니며 피연산자 중 하나를 문자열로 캐스팅 한 후에 실제로는 빈 문자열입니다.
또 다른 흥미로운 사실은 C # / .NET 에서null 다른 데이터 형식을 고려할 때 처리 방식 이 항상 동일하지는 않다는 것 입니다. 예를 들면 다음과 같습니다.
int? x = 1; // string x = "1";
x = x + null + null;
Console.WriteLine((x==null) ? "<null>" : x.ToString());
코드 스 니펫 의 첫 번째 줄 에 대해 : value를 포함 x하는 nullable 정수 변수 인 경우 결과를 다시 얻습니다 . 이 값 (같은 주석 참조) 문자열 인 경우 에, 당신은 얻고 다시보다는 .int?1<null>"1""1"<null>
NB 또한 흥미로운 점 : var x = 1;첫 번째 줄에 사용 하는 경우 런타임 오류가 발생합니다. 왜? 할당은 변수 x를 datatype으로 변환하므로 intnullable은 아닙니다. 컴파일러는 int?여기서 가정하지 않으므로 null추가 된 두 번째 줄에서 실패합니다 .
null문자열에 추가 하는 것은 단순히 무시됩니다. null(두 번째 예에서)는 객체의 인스턴스가 아니므로 ToString()메소드 조차 없습니다 . 그냥 리터럴입니다.
null.ToString()의 이름이 주어진다는 것이 특별하다는 것을 알게되었습니다wtf. 왜 놀랍습니까? 처음부터 호출 할 것이 없으면 인스턴스 메소드를 호출 할 수 없습니다.