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

标签 c# parameter-passing pass-by-reference value-type

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

在方法声明中使用 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,等等。

还有一个事实是,运算符重载没有传统的方法“调用点”可以用(尽管是可选的)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 注释,任何行为都适用于作为运算符的静态方法,以及作为使用这些运算符的表达式的静态方法调用。

关于C#7 'in' 允许运算符重载的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48570084/

相关文章:

c# - EF6 中的急切、延迟和显式加载

c# - 如果 Observable 的订阅者需要触发 OnNext() 怎么办?

C 在参数类型为 int** 的情况下将 int* 作为参数会发生什么情况?

function - 无法使用另一个函数中的一个函数的变量

java - 在 Java 中传递的可选匿名参数

c# - C#取算符

c# - 计算 WPF 或 SVG 图形的坐标点

Javascript通过引用访问成员变量

python - 为什么这个空字典会破坏共享引用?

c++ - 双指针有必要吗?