Does passing a struct into an interface field allocate?
I have a structure something like this
struct MyStructure
:IFoo
{
}
and a method like this:
public BarThisFoo(IFoo a)
{
}
my question is does passing the structure into that method "box" the structure, thus causing a garbage allocation?
Addendum: Before anyone says it, garbage collection is not free in this application, it's actually very sensitive to garbage collections, so allocation free code is important.
Yes, it does. Boxing occurs whenever you convert from:
System.ValueType
reference System.Enum
reference This is case III, obviously. You can read a more thorough example here .
To avoid boxing you can use generics with constraints:
struct MyStructure
:IFoo
{
}
public void BarThisFoo<T>(T a) where T : IFoo
{
}
See J. Richter CLR via C#, 2nd edition, chapter 14: Interfaces, section about Generics and Interface Constraints.
EDIT:
Example code
using System;
using System.Collections;
interface IFoo {
void Foo();
}
struct MyStructure : IFoo {
public void Foo() {
}
}
public static class Program {
static void BarThisFoo<T>(T t) where T : IFoo {
t.Foo();
}
static void Main(string[] args) {
MyStructure s = new MyStructure();
BarThisFoo(s);
}
}
IL code for method Main doesn't contain any box instructions:
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 15 (0xf)
.maxstack 1
.locals init ([0] valuetype MyStructure s)
IL_0000: ldloca.s s
IL_0002: initobj MyStructure
IL_0008: ldloc.0
IL_0009: call void Program::BarThisFoo<valuetype MyStructure>(!!0)
IL_000e: ret
} // end of method Program::Main
As others have noted, yes, converting a struct to an interface it implements is a boxing cast. More important is not what the answer to the question is, but that you be able to answer it yourself. If you use ILDASM to disassemble a test application, you'll see that the "box" instruction is generated by the compiler at the point of the conversion. Now next time you have a question about boxing, you can just write yourself a test program, disassemble it, and then you'll know.
Incidentally, note that boxing does NOT happen if you call a method on an implicitly implemented interface method on a struct:
struct S : IFoo { public void Foo() { ...
...
myS.Foo(); // no boxing
((IFoo)myS).Foo(); // boxing
This is particularly relevant for interface methods on mutable value types; remember, if you're mutating a boxed value type then you're mutating the value in the box, not the variable that originally contained the boxed value. The fact that myS.Foo() and ((IFoo)myS).Foo() can have different semantics is yet another reason why mutable value types are pure evil and should be avoided.
链接地址: http://www.djcxy.com/p/52834.html上一篇: Func <>委托有什么好处?
下一篇: 是否将结构传递到接口字段分配?