Neden bu=! check boş?
Bazen biraz zaman geçirmek için seviyorum .NET sadece perde arkasında bazı nasıl uygulandığını görmek için kod. Reflektör) String.Equals
yöntemi bakarken bu taş sendeledi.
C#
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public override bool Equals(object obj)
{
string strB = obj as string;
if ((strB == null) && (this != null))
{
return false;
}
return EqualsHelper(this, strB);
}
IL
.method public hidebysig virtual instance bool Equals(object obj) cil managed
{
.custom instance void System.Runtime.ConstrainedExecution.ReliabilityContractAttribute::.ctor(valuetype System.Runtime.ConstrainedExecution.Consistency, valuetype System.Runtime.ConstrainedExecution.Cer) = { int32(3) int32(1) }
.maxstack 2
.locals init (
[0] string str)
L_0000: ldarg.1
L_0001: isinst string
L_0006: stloc.0
L_0007: ldloc.0
L_0008: brtrue.s L_000f
L_000a: ldarg.0
L_000b: brfalse.s L_000f
L_000d: ldc.i4.0
L_000e: ret
L_000f: ldarg.0
L_0010: ldloc.0
L_0011: call bool System.String::EqualsHelper(string, string)
L_0016: ret
}
null
karşı this
kontrol gerekçesi nedir? Bu muhtemelen yakalandı ve şimdi kaldırdınız ki başka bir amaç yok sanıyorum.
CEVAP
Sonunda aradığını varsayıyorum .NET 3.5 uygulama? Bu inanıyorum .NET 4 Uygulama biraz farklı.
Ancak, olası bile sanal örnek yöntemleri olmayan hemen hemen diyoruz çünkü bu bir sinsi bir şüphe varnull bir referans. Mümkün IL. null.Equals(null)
çağıran bazı IL üretmek miyim, bir bakayım.
EDİT: Tamam, İşte bazı ilginç kod:
.method private hidebysig static void Main() cil managed
{
.entrypoint
// Code size 17 (0x11)
.maxstack 2
.locals init (string V_0)
IL_0000: nop
IL_0001: ldnull
IL_0002: stloc.0
IL_0003: ldloc.0
IL_0004: ldnull
IL_0005: call instance bool [mscorlib]System.String::Equals(string)
IL_000a: call void [mscorlib]System.Console::WriteLine(bool)
IL_000f: nop
IL_0010: ret
} // end of method Test::Main
Aşağıdaki C derleme olarak bunu aldım# kod:
using System;
class Test
{
static void Main()
{
string x = null;
Console.WriteLine(x.Equals(null));
}
}
... ve sonra sökülmesi ile 19* *ve düzenleme. Bu satırı not:
IL_0005: call instance bool [mscorlib]System.String::Equals(string)
Aslında, o call
yerine callvirt
.
Biz yeniden birleştirmek zaman ne olacak? Peki, ile .NET 4.0 bu elde ederiz
Unhandled Exception: System.NullReferenceException: Object
reference not set to an instance of an object.
at Test.Main()
Hmm. Ne hakkında .NET 2.0?
Unhandled Exception: System.NullReferenceException: Object reference
not set to an instance of an object.
at System.String.EqualsHelper(String strA, String strB)
at Test.Main()
Şimdi daha ilginç... açıkça normalde tahmin edemezdik EqualsHelper
girmeye başardık.
Dize kadar... hadi referans eşitlik kendimizi uygulamak, null.Equals(null)
doğru dönmek alabiliriz olup olmadığını görmek için deneyin:
using System;
class Test
{
static void Main()
{
Test x = null;
Console.WriteLine(x.Equals(null));
}
public override int GetHashCode()
{
return base.GetHashCode();
}
public override bool Equals(object other)
{
return other == this;
}
}
Daha önce olduğu gibi aynı prosedür, call
, tekrar kurmak callvirt
demonte değiştirmek ve true
izle. baskı
Başka başvurular yanıtlar rağmen this C question diyoruz çünkü burada daha dolambaçlı... olduğumuzu unutmayınsanalyöntem-neredeyse olmayan. Hatta C /CLİ derleyici sanal bir yöntem için callvirt
kullanır normalde. Diğer bir deyişle, bu durumda bence this
boş olmak için tek yolu elle IL yazmaktır.
EDİT: bir şey fark ettim... aslında doğru yöntem aramadımyaküçük bir örnek program. İşte ilk durumda: çağrı
IL_0005: call instance bool [mscorlib]System.String::Equals(string)
işte bu da ikincisi: Ara
IL_0005: call instance bool [mscorlib]System.Object::Equals(object)
İlk durumda, bendemek35 ** ve ikinci arayacağımdemekTest::Equals(object)
Ara. Bu üç şey görebiliriz:
- Aşırı dikkatli olmak gerekir.
- C# derleyicisi yaydığı için çağırırdeclarersanal yöntemi - en Belirli değilgeçersiz kılarsanal yöntemi. IIRC, VB ters şekilde çalışır
object.Equals(object)
"" referans . bu bir boş karşılaştırmak için mutlu
Eğer C çıkış konsolu biraz eklerseniz# override, farkı görebilirsiniz - IL açıkça, bu şekilde aradığım için değiştirmediğiniz sürece denilen olmayacak:
IL_0005: call instance bool Test::Equals(object)
Yani, biz vardır. Null referanslar örnek yöntemleri eğlenceli ve istismar.
Eğer bu güne kadar yaptık, ayrıca IL how value types can declare parameterless constructors... hakkında blog yazısı bakmak isteyebilirsiniz.
Neden sıralanmamış bir dizi daha hızlı...
Neden bu iki kez (1927) garip bir sonu...
Neden HTML düşün” renk? “chucknorris m...
Neden Google while(1); JSON yanıtların...
Neden char[] şifreler için Dize Java t...