Gle*_*den 7 c# parameter-passing value-type pass-by-reference
最近添加到C#7非常棒,现在在最新版本中,我们可以通过使用new 关键字更有效地将ValueType(struct)实例传递给函数by-reference('by-ref')in.
在方法声明中使用in或使用或者ref意味着您可以避免struct为了保留按值语义而通常需要的整个额外的"memory-blt"副本.使用in,您可以获得此优势(将指针传递给源ValueType本身),但不同ref的是,不允许被调用者修改该目标(编译器强制执行).
除了提高设计意图的严谨性之外,in还有一个额外的好处,ref即调用站点语法比使用它更加轻松ref.实际上,您不需要in在呼叫站点提及关键字; 这是可选的.
无论如何,我注意到你显然可以使用-attributed arguments 来定义C#运算符重载in.
public static bool operator ==(in FILE_ID_INFO x, in FILE_ID_INFO y) => eq(in x, in y);
// works: -----^ -----^
Run Code Online (Sandbox Code Playgroud)
如果by-ref语义实际上在运行时行为中占优势,那么这很好.但我会发现这很令人惊讶,因为即使C#允许您in在方法调用中省略关键字,调用站点生成的代码也需要不同.即,它需要发射(例如)OpCodes.Ldflda而不是OpCodes.Ldfld等等.
然后还有一个事实是,运算符重载没有传统方法"调用站点",可以使用(尽管是可选的)in关键字进行修饰:
var fid1 = default(FILE_ID_INFO);
var fid2 = default(FILE_ID_INFO);
bool q = fid1 == fid2;
// ^--- in? ---^
Run Code Online (Sandbox Code Playgroud)
那么,有没有人知道编译器,JIT和运行时是否会尊重代码似乎允许表达的内容,这样使用in-parameters 调用操作符重载实际上会获得by-ref语义?我找不到文档中的情况.由于上面显示的代码基本上继续工作,因为它没有in标记,我想替代方案是in关键字在这里被默默忽略?
简短回答:编译器做对了.相信编译器.
答案很长:
重载运算符只是静态方法的语法糖.调用重载的运算符只是调用该方法的语法糖.
那是,
public static bool operator ==(S s1, S s2) { ... }
Run Code Online (Sandbox Code Playgroud)
对于类似的东西来说,它只是一种语法糖
public static bool op_Equality(S s1, S s2) { ... }
Run Code Online (Sandbox Code Playgroud)
和
if (s1 == s2)
Run Code Online (Sandbox Code Playgroud)
只是一个语法糖
if (S.op_Equality(s1, s2))
Run Code Online (Sandbox Code Playgroud)
因此,in对于普通静态方法和常规静态方法调用的注释,无论行为是什么,也适用于作为运算符的静态方法,以及使用这些运算符的表达式的静态方法调用.