La chiamata di un metodo su un tipo di valore comporta un inscatolamento in .NET?
-
22-07-2019 - |
Domanda
Stavo solo partecipando alla domanda Stack Overflow È tutto in .NET un obiettare? .
E un poster (nei commenti della risposta accettata) sembrava pensare che l'esecuzione di una chiamata del metodo su un tipo di valore causasse un inscatolamento. Mi ha indicato Boxing and Unboxing (Programmazione C # Guida) che non specifica esattamente il caso d'uso che stiamo descrivendo.
Non sono uno che si fida di una singola fonte, quindi volevo solo ottenere ulteriori feedback sulla domanda. La mia intuizione è che non c'è boxe ma la mia intuizione fa schifo. : D
Per elaborare ulteriormente:
L'esempio che ho usato era:
int x = 5;
string s = x.ToString(); // Boxing??
La boxe non si verifica se la struttura in questione sovrascrive il metodo ereditato dall'oggetto come afferma la risposta accettata qui.
Tuttavia, se la struttura non sostituisce il metodo, un "vincolo" Il comando CIL viene eseguito prima di una chiamata. Secondo la documentazione, OpCodes. Campo vincolato , questo si traduce in boxe :
Se thisType è un tipo di valore e thisType non implementa il metodo quindi ptr è dereferenziato, inscatolato e passato come puntatore "questo" a istruzione del metodo callvirt.
Soluzione
Ecco l'IL per il tuo codice:
L_0001: ldc.i4.5 // get a 5 on the stack
L_0002: stloc.0 // store into x
L_0003: ldloca.s x // get the address of x on the stack
L_0005: call instance string [mscorlib]System.Int32::ToString() // ToString
L_000a: stloc.1 // store in s
Quindi la risposta in questo caso è no.
Altri suggerimenti
Nel caso in cui tu abbia dato la risposta è no, come ha sottolineato lo zoccolo.
Tuttavia, lo farà se si chiama un metodo tramite un puntatore all'interfaccia.
Considera il codice:
interface IZot
{
int F();
}
struct Zot : IZot
{
public int F()
{
return 123;
}
}
Poi
Zot z = new Zot();
z.F();
non si traduce in boxe:
.locals init (
[0] valuetype ConsoleApplication1.Zot z)
L_0000: nop
L_0001: ldloca.s z
L_0003: initobj ConsoleApplication1.Zot
L_0009: ldloca.s z
L_000b: call instance int32 ConsoleApplication1.Zot::F()
L_0010: pop
L_0011: ret
Tuttavia, ciò fa:
IZot z = new Zot();
z.F();
.locals init (
[0] class ConsoleApplication1.IZot z,
[1] valuetype ConsoleApplication1.Zot CS<*><*>)
L_0000: nop
L_0001: ldloca.s CS<*><*>
L_0003: initobj ConsoleApplication1.Zot
L_0009: ldloc.1
L_000a: box ConsoleApplication1.Zot
L_000f: stloc.0
L_0010: ldloc.0
L_0011: callvirt instance int32 ConsoleApplication1.IZot::F()
L_0016: pop
@ ggf31316
" Credo che chiamando ToString, Risultati uguali e Gethashcode boxe se la struttura no sovrascrivere i metodi. "
Ho controllato ToString per te. Int32 ignora ToString, quindi ho creato una struttura che non lo fa. Ho usato .NET Reflector per assicurarmi che la struttura non fosse in qualche modo magicamente dominante su ToString () e non lo era.
Quindi il codice era così:
using System;
namespace ConsoleApplication29
{
class Program
{
static void Main(string[] args)
{
MyStruct ms = new MyStruct(5);
string s = ms.ToString();
Console.WriteLine(s);
}
}
struct MyStruct
{
private int m_SomeInt;
public MyStruct(int someInt)
{
m_SomeInt = someInt;
}
public int SomeInt
{
get
{
return m_SomeInt;
}
}
}
}
E MSIL (tramite ILDASM ) per il metodo principale è questo:
IL_0000: ldloca.s ms
IL_0002: ldc.i4.5
IL_0003: call instance void ConsoleApplication29.MyStruct::.ctor(int32)
IL_0008: ldloca.s ms
IL_000a: constrained. ConsoleApplication29.MyStruct
IL_0010: callvirt instance string [mscorlib]System.Object::ToString()
IL_0015: stloc.1
IL_0016: ldloc.1
IL_0017: call void [mscorlib]System.Console::WriteLine(string)
IL_001c: ret
Ora, nonostante non avvenga alcuna chiamata di boxe, se si seleziona la documentazione su un vincolato + un virt virt , troverete che afferma che la boxe ha luogo. oOo
Quote:
Se thisType è un tipo di valore e thisType non implementa il metodo quindi ptr è dereferenziato, inscatolato e passato come puntatore "questo" a istruzione del metodo callvirt.
Credo che chiamare ToString, Equals e Gethashcode comporti un inscatolamento se la struttura non sovrascrive i metodi.