Dans .NET si vous passez un struct dans une méthode avec un paramètre d'interface-t-il la valeur boîte?
Question
A partir d'un simple test, je peux voir que si vous passez la struct dans la méthode, il est passé par valeur, mais si vous devez d'abord l'attribuer à une interface, il est passé par référence.
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
Alors ma question est, est-il encore une opération de boxe pour faire passer une struct dans comme ça?
La solution
Whenever a struct gets converted to an interface it gets boxed.
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
You can avoid that boxing by making the parameter generic using the interface as a constraint:
void Bar<T>(T foo)
where T:IFoo
{
}
This uses the fact that generics get specialized for every value type.
But if you follow the design guideline that mutable strucs are evil, and thus make your struct immutable, it doesn't matter much if the code boxes or not. The boxing then only causes a slight performance hit, but doesn't change semantics much.
Autres conseils
Interfaces are all reference types, so the boxing occurs on the line
IFoo ifoo = new Foo();
rather than when calling Bar
.