C #에서 (this == null)!
C # 4에서 수정 된 버그로 인해 다음 프로그램이 인쇄 true
됩니다. (LINQPad에서 사용해보십시오)
void Main() { new Derived(); }
class Base {
public Base(Func<string> valueMaker) { Console.WriteLine(valueMaker()); }
}
class Derived : Base {
string CheckNull() { return "Am I null? " + (this == null); }
public Derived() : base(() => CheckNull()) { }
}
릴리스 모드의 VS2008에서는 InvalidProgramException이 발생합니다. (디버그 모드에서는 제대로 작동합니다)
VS2010 Beta 2에서는 컴파일되지 않습니다 (베타 1을 시도하지 않았습니다). 어려운 방법을 배웠습니다
this == null
순수한 C # 으로 만드는 다른 방법이 있습니까?
이 관찰은 오늘 초 또 다른 질문 으로 StackOverflow에 게시되었습니다 .
이 질문에 대한 Marc 의 훌륭한 답변 은 사양 (섹션 7.5.7)에 따라 this
해당 컨텍스트에서 액세스 할 수 없어야 하며 C # 3.0 컴파일러에서 액세스 할 수 있는 기능은 버그라는 것을 나타냅니다. C # 4.0 컴파일러는 사양에 따라 올바르게 작동합니다 (베타 1에서도 컴파일 시간 오류 임).
§ 7.5.7이 액세스
A는 이 액세스는 예약어로 구성된다
this
.이 액세스 :
this
(A)는 ,이 액세스는 단지 허용되는 블록 인스턴스 생성자 인스턴스 메소드 또는 인스턴스 액세서.
디버그 모드 바이너리의 원시 디 컴파일 (최적화가없는 반사판)은 다음과 같습니다.
private class Derived : Program.Base
{
// Methods
public Derived()
{
base..ctor(new Func<string>(Program.Derived.<.ctor>b__0));
return;
}
[CompilerGenerated]
private static string <.ctor>b__0()
{
string CS$1$0000;
CS$1$0000 = CS$1$0000.CheckNull();
Label_0009:
return CS$1$0000;
}
private string CheckNull()
{
string CS$1$0000;
CS$1$0000 = "Am I null? " + ((bool) (this == null));
Label_0017:
return CS$1$0000;
}
}
CompilerGenerated 메소드는 의미가 없습니다. IL (아래)을 보면 null 문자열 (!) 에서 메소드를 호출합니다 .
.locals init (
[0] string CS$1$0000)
L_0000: ldloc.0
L_0001: call instance string CompilerBug.Program/Derived::CheckNull()
L_0006: stloc.0
L_0007: br.s L_0009
L_0009: ldloc.0
L_000a: ret
릴리스 모드에서는 로컬 변수가 최적화되어 존재하지 않는 변수를 스택으로 푸시하려고 시도합니다.
L_0000: ldloc.0
L_0001: call instance string CompilerBug.Program/Derived::CheckNull()
L_0006: ret
(리플렉터가 C #으로 전환되면 작동이 중단됩니다)
편집 : 누군가 (Eric Lippert?) 컴파일러가 왜 방출 ldloc
합니까?
나는 그것을 가졌다! (그리고 증거도 얻었습니다)
이것은 "버그"가 아닙니다. 이것은 타입 시스템을 남용하는 것입니다. 현재 인스턴스 ( this
)에 대한 참조를 생성자 내의 모든 사람 에게 전달해서는 안됩니다 .
기본 클래스 생성자 내에서 가상 메서드를 호출하여 비슷한 "버그"를 만들 수 있습니다.
Just because you can do something bad doesn't mean its a bug when you get bit by it.
I could be wrong, but I'm pretty sure if your object is null
there's never going to be a scenario where this
applies.
For instance, how would you call CheckNull
?
Derived derived = null;
Console.WriteLine(derived.CheckNull()); // this should throw a NullReferenceException
Not sure if this is what you are looking for
public static T CheckForNull<T>(object primary, T Default)
{
try
{
if (primary != null && !(primary is DBNull))
return (T)Convert.ChangeType(primary, typeof(T));
else if (Default.GetType() == typeof(T))
return Default;
}
catch (Exception e)
{
throw new Exception("C:CFN.1 - " + e.Message + "Unexpected object type of " + primary.GetType().ToString() + " instead of " + typeof(T).ToString());
}
return default(T);
}
example: UserID = CheckForNull(Request.QueryString["UserID"], 147);
참고URL : https://stackoverflow.com/questions/1600662/this-null-in-c
'IT' 카테고리의 다른 글
CSS : 글꼴 크기 100 %-무엇의 100 %? (0) | 2020.07.04 |
---|---|
Ansible 역할에서 기본값과 vars의 차이점은 무엇입니까? (0) | 2020.07.04 |
부울, 조건부 연산자 및 오토 박싱 (0) | 2020.07.04 |
Node.js와 함께 사용할 수있는 최고의 테스트 프레임 워크는 무엇입니까? (0) | 2020.07.04 |
Java 문자열에서 hashCode ()의 일관성 (0) | 2020.07.04 |