C#7 'in' 允许运算符重载的参数

C#7 'in' parameters allowed with operator overloading

最近对 C# 7 的添加很棒,现在在最新版本中我们可以通过引用将 ValueType (struct) 个实例传递给函数('by-ref') 通过使用新的 in 关键字更有效。

在方法声明中使用 inref 意味着您可以避免整个 struct 的额外 'memory-blt' 副本,这通常是为了保留按值语义。使用 in,您可以获得此好处(传递指向源 ValueType 本身的指针),但与 ref 不同,不允许被调用者修改该目标(由编译器强制执行) ).

除了提高设计意图的严谨性之外,inref 有一个额外的好处,即调用站点语法比 ref 更宽松。事实上,您不需要在调用站点提及 in 关键字;这是可选的。

无论如何,我注意到您显然可以使用 in 属性参数定义 C# 运算符重载

public static bool operator ==(in FILE_ID_INFO x, in FILE_ID_INFO y) => eq(in x, in y);
//       works:            -----^            -----^

如果 by-ref 语义 在运行时确实占主导地位 ,那就太好了行为。但我会发现这令人惊讶,因为即使 C# 允许您在方法调用中省略 in 关键字,调用站点处生成的代码 是否需要不同。也就是说,它需要发出(例如)OpCodes.Ldflda 而不是 OpCodes.Ldfld,等等。

还有一个事实是运算符重载没有传统方法 "call site" 可以用(尽管是可选的)in 关键字修饰:

var fid1 = default(FILE_ID_INFO);
var fid2 = default(FILE_ID_INFO);

bool q =    fid1 ==    fid2;
//       ^--- in? ---^      

所以,有谁知道编译器、JIT 和运行时是否会遵守代码似乎允许表达的内容,这样调用带有 in 参数的运算符重载实际上将获得 by-ref 语义?我在文档中找不到任何关于这种情况的提及。由于上面显示的代码基本上继续像没有 in 标记一样工作,我想替代方案是 in 关键字在这里被默默地忽略?

简短回答:编译器做了正确的事情。相信编译器。

长答案:

重载运算符只是静态方法的语法糖。重载运算符的调用只是调用该方法的语法糖。

public static bool operator ==(S s1, S s2) { ... }

只是

之类的语法糖
public static bool op_Equality(S s1, S s2) { ... }

if (s1 == s2)

只是

的语法糖
if (S.op_Equality(s1, s2))

因此,无论 in 普通静态方法和普通静态方法调用上的注释的行为如何,也适用于作为运算符的静态方法和作为使用这些运算符的表达式的静态方法调用。