2013-06-27 3 views
21

Bitte helfen Sie, dieses Verhalten zu verstehen. Wenn ich dies:C# Verkettungszeichenfolgen beim Kompilieren

bool a1 = (object)("string" + 1) == ("string" + 1); 

Das Ergebnis ist false

Aber wenn ich diese verwenden

bool a2 = (object)("string" + "1") == ("string" + "1"); 

Das Ergebnis ist true

Also, warum a1 != a2?

+0

Ich weiß nicht genau warum, aber ich weiß, Sie sollten nicht Zeichenfolge Qualität mit „==“ sowieso checken. object1.equals (object2) ist der Weg dahin, zumindest zu meinem Verständnis. Ich habe dies jedoch nicht als Antwort gepostet, weil es Ihre Frage wahrscheinlich nicht beantwortet. –

+0

Überprüfen Sie dies: http://stackoverflow.com/questions/3398604/string-string-int-whats-behind-the-scene-c – Ani

+1

@Ricky Mutschlechner: AFAIK der Operator '==' == '.equals'. ;-) –

Antwort

34

Casting nach object erzwingt einen Vergleich der Referenzgleichheit.

Im ersten Fall werden zur Laufzeit zwei verschiedene string Objekte generiert. Da es sich um verschiedene Instanzen handelt, ist das Ergebnis falsch.

Im zweiten Fall merkt der Compiler, dass "string" + "1" wird immer "string1" und Praktikanten die Zeichenfolge und verwendet die gleiche Referenz an beiden Orten. Da es sich um dieselbe Zeichenfolgenreferenz handelt, ist das Ergebnis wahr.

+2

@OP Nur um hinzuzufügen, sollten Sie immer Zeichenfolgen mit String.Equals – Mataniko

+0

+1 vergleichen. Ich liebe diese Antwort. Danke :) –

+10

@Mataniko Nein, Sie sollten nur sicherstellen, dass Ihre Variablen einer Kompilierzeit Typ Zeichenfolge sind, wenn Sie 'operator ==' verwenden. Verwenden Sie 'string.Equals' nur dann, wenn eines oder mehrere der Objekte nicht statisch in' string' eingetippt sind (was eigentlich ziemlich selten sein sollte). – Servy

19

Es gibt zwei wichtige Dinge, die sich hier:

Zuerst Der Ausdruck "string" + 1 wird zur Laufzeit ausgewertet, während "string" + "1" zur Compile-Zeit ausgewertet wird.

Zweitens verwenden Sie Referenzvergleich. Die von der Laufzeit generierten Strings verweisen auf ein anderes Objekt, während die generierten Strings zur Kompilierzeit auf dasselbe Objekt verweisen. Daher lautet der erste Ausdruck und der zweite Ausdruck true.

Wenn Sie interessiert sind, die erzeugte IL ist:

// bool a1 = (object)("string" + 1) == ("string" + 1); 
// bool a2 = (object)("string" + "1") == ("string" + "1"); 

IL_0000: ldstr  "string" 
IL_0005: ldc.i4.1  
IL_0006: box   System.Int32 
IL_000B: call  System.String.Concat 
IL_0010: ldstr  "string" 
IL_0015: ldc.i4.1  
IL_0016: box   System.Int32 
IL_001B: call  System.String.Concat 
IL_0020: ceq   
IL_0022: stloc.0  // a1 
IL_0023: ldstr  "string1" 
IL_0028: ldstr  "string1" 
IL_002D: ceq   
IL_002F: stloc.1  // a2 
+3

+1 für die Buchung der IL: P –

+0

Ordentlich. Interessiert zu erwähnen, wie man IL so sehen würde? – kenchilada

+1

@radium Persönlich verwende ich [ILSpy] (http://ilspy.net/). –