In .NET Se si passa una struttura in un metodo con un parametro di interfaccia, è in casella il valore?

StackOverflow https://stackoverflow.com/questions/5363587

  •  27-10-2019
  •  | 
  •  

Domanda

Da un semplice test posso vedere che se si passa la struttura nel metodo viene passata per valore ma se la assegni per la prima volta a un'interfaccia viene passata per riferimento.

interface IFoo { int Val { get; set; } }
struct Foo : IFoo { public int Val { get; set; } }

void Bar(IFoo foo) { foo.Val = 1; }

Foo foo = new Foo();
IFoo ifoo = new Foo();

Bar(foo);
Bar(ifoo);

Console.WriteLine(foo.Val);  // 0, passed by value
Console.WriteLine(ifoo.Val); // 1, passed by ref

Quindi la mia domanda è: c'è ancora un'operazione di boxe per passare una struttura in questo modo?

È stato utile?

Soluzione

Ogni volta che una struttura viene convertita in un'interfaccia, viene inscatolata.

Foo foo = new Foo();//Doesn't box yet
IFoo ifoo = new Foo();//Boxes

Bar(foo);//creates a new boxed copy
Bar(ifoo);//Uses the old boxed version created in line 2

Puoi evitare quella boxe rendendo il parametro generico usando l'interfaccia come vincolo:

void Bar<T>(T foo)
    where T:IFoo 
{
}

Questo utilizza il fatto che i generici si specializzano per ogni tipo di valore.


Ma se segui la linea guida del design che gli strucci mutabili sono malvagi e quindi rendi immutabile la tua struttura, non importa molto se le caselle di codice o meno. La boxe provoca solo un leggero colpo di prestazione, ma non cambia molto la semantica.

Altri suggerimenti

Le interfacce sono tutte tipi di riferimento, quindi la boxe si verifica sulla linea

IFoo ifoo = new Foo();

piuttosto che quando si chiama Bar.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top