是否将结构传递到接口字段分配?
我有一个像这样的结构
struct MyStructure
:IFoo
{
}
和一个像这样的方法:
public BarThisFoo(IFoo a)
{
}
我的问题是将结构传递给该方法“框”的结构,从而导致垃圾分配?
附录:在任何人说出来之前,垃圾收集在这个应用程序中并不是免费的,它实际上对垃圾收集非常敏感,所以免费分配代码很重要。
是的,它确实。 每当您从以下位置转换时都会发生拳
System.ValueType
引用 System.Enum
引用 很明显,情况三。 你可以在这里阅读更详尽的例子。
为了避免装箱,你可以使用带有约束的泛型:
struct MyStructure
:IFoo
{
}
public void BarThisFoo<T>(T a) where T : IFoo
{
}
请参阅J. Richter CLR,通过C#,第2版,第14章:接口,关于泛型和接口约束的章节。
编辑:
示例代码
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代码Main不包含任何框指令:
.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
正如其他人已经指出的,是的,将一个结构转换为它实现的接口是一个装箱。 更重要的不是问题的答案是什么,而是你能够自己回答。 如果使用ILDASM反汇编测试应用程序,则会看到“编译器”指令是在编译器转换时生成的。 现在下一次你有关于拳击的问题,你可以写一个测试程序,拆卸它,然后你就会知道。
顺便提一句,请注意,如果您在结构上的隐式实现的接口方法上调用方法,则不会发生装箱:
struct S : IFoo { public void Foo() { ...
...
myS.Foo(); // no boxing
((IFoo)myS).Foo(); // boxing
这对于可变值类型的接口方法特别重要; 请记住,如果你正在改变盒装值类型,那么你在框中改变值,而不是最初包含盒装值的变量。 myS.Foo()和((IFoo)myS).Foo()可以具有不同的语义这一事实是可变值类型为纯邪恶并应该避免的另一个原因。
链接地址: http://www.djcxy.com/p/52833.html上一篇: Does passing a struct into an interface field allocate?