Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/296.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当将结构值作为接口值传递时,如何避免装箱?_C# - Fatal编程技术网

C# 当将结构值作为接口值传递时,如何避免装箱?

C# 当将结构值作为接口值传递时,如何避免装箱?,c#,C#,接口(I)是引用类型,结构(S)是值类型。结构可以实现接口 public interface I {} struct S: I {} 假设有一个S的值作为I的参数传递给一个方法。在这种情况下,它必须被装箱 void Method(I i) {} void Test() { var s = new S(); this.Method(s); // <---- boxing! } void方法(I){ 无效测试(){ var s=新的s(); 如果将方法的定义更改为: void

接口(I)是引用类型,结构(S)是值类型。结构可以实现接口

public interface I {}
struct S: I {}
假设有一个S的值作为I的参数传递给一个方法。在这种情况下,它必须被装箱

void Method(I i) {}

void Test() {
   var s = new S();
   this.Method(s); // <---- boxing!
}
void方法(I){
无效测试(){
var s=新的s();

如果将
方法
的定义更改为:

void Method<T>(T i) where T : I
{
}
使用泛型:

public interface I {}
public struct S : I {}
public class Foo
{
    public static void Bar<T>(T i)
        where T : I
    {}
}
公共接口I{}
公共结构S:I{}
公开课Foo
{
公共静态空栏(TI)
T:我在哪里
{}
}

听起来像是一个潜在的面试问题……我会尽量记住一个问题您是否忘记了结构约束?其中T:struct,I@BradRem:如果在编译时传入类型时知道它,C#类型推断将开始,这就像调用
方法一样
。此时可以识别出您正在使用结构,并将避免装箱。编辑:但是,如果您在编译时不知道
s
的类型(即,您仅将其作为接口
i
键入,比如编写:
i s=new s()
),则它仍将装箱。(当然,在那一点上,它已经被装箱了,所以实际上没有太多需要做的事情)您关于装箱将在调用Equals和GetHashCode时发生的语句仅部分正确。如果结构未重写这些方法,装箱将在这些调用中发生。如果这些方法被重写,编译器将生成直接调用这些方法的代码,而不是通过vtable。@EricLippert-感谢您的更正。如果从重写的方法调用基本实现,这仍然适用吗?既然
ValueType
是引用类型,那么装箱是否需要发生,因此
this
是引用而不是结构本身?@Lee:基本实现需要类型为
object
this
,所以是的,它必须装箱。另外,
GetType
不能被重写,因为它不是虚拟的,所以接收方总是被装箱——但是,再说一遍,为什么要对未装箱的结构调用
GetType
?您已经知道它的类型了!
public interface I {}
public struct S : I {}
public class Foo
{
    public static void Bar<T>(T i)
        where T : I
    {}
}