?
Guten Morgen,
Ich finde den Fall bemerkenswert interessant und kann ihn reproduzieren. Klären kann man ihn sehr gut indem man sich den IL-Code genau anschaut:
.method assembly static void func(string& d, object& c) cil managed
{
.maxstack 2
L_0000: ldarg.1
L_0001: ldstr "new string 1"
L_0006: stind.ref
L_0007: ldarg.0
L_0008: ldstr "new string 2"
L_000d: stind.ref
L_000e: ret
}
.method assembly static int32 modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl) main() cil managed
{
.maxstack 3
.locals (
[0] string b,
[1] string a,
[2] int32 num,
[3] object obj2)
L_0000: ldc.i4.0
L_0001: stloc.2
L_0002: ldnull
L_0003: stloc.1
L_0004: ldnull
L_0005: stloc.0
L_0006: ldstr "old string 1"
L_000b: stloc.1
L_000c: ldstr "old string 2"
L_0011: stloc.0
L_0012: ldloc.0
L_0013: stloc.3
L_0014: ldloca.s a
L_0016: ldloca.s obj2
L_0018: call void <Module>::func(string&, object&)
L_001d: ldstr "{0}\n{1}"
L_0022: ldloc.1
L_0023: ldloc.0
L_0024: call void [mscorlib]System.Console::WriteLine(string, object, object)
L_0029: ldc.i4.0
L_002a: stloc.2
L_002b: ldloc.2
L_002c: ret
}
Meine Analyse: Bei main/L_0011 speicherst du die Referenz auf den konstanten "old string 2" in b (stloc.0), nachher wird dieselbe Referenz mit stloc.3, siehe L_0013, in einem temporären Feld gespeichert. Vor dem Aufruf der Funktion wird bei L_0016 mittels ldloca.s die Adresse des temporären Feldes auf den Stack geladen; konsequenterweise wird daher bei func/L_000d (stind.ref) auch nur das temporäre Feld überschrieben. Bei der Ausgabe der Strings wird jedoch wieder der ursprüngliche String geladen (L_0023, ldloc.0). Ich glaube nicht, dass dieses Verhalten vom Compilerhersteller gewünscht war. Es ist vermutlich ein Bug oder so, melde es doch mal
Viel Vergnügen noch