C# 7.2 对运算符使用“in parameter”

Posted

技术标签:

【中文标题】C# 7.2 对运算符使用“in parameter”【英文标题】:C# 7.2 use of "in parameter" for operators 【发布时间】:2019-03-18 01:31:27 【问题描述】:

在 C# 7.2 中,我们看到为方法参数引入了 in 修饰符,以将只读引用传递给对象。我正在使用 7.2 开发一个新的 .NET Standard 项目,出于好奇,我尝试在结构的相等运算符的参数上使用 in 关键字进行编译。

即- public static bool operator == (in Point l, in Point r)

不是 - public static bool operator == (Point l, Point r)

一开始我对这行得通感到有些惊讶,但经过一番思考后,我意识到这两个版本的运算符之间可能没有功能差异。我想确认这些怀疑,但经过一番彻底的搜索后,我找不到任何明确谈论在运算符重载中使用 in 关键字的内容。

所以我的问题是这是否真的有功能差异,如果有,是否有任何特别的理由鼓励或不鼓励使用 in 和运算符参数。我最初的想法是没有区别,特别是如果操作符是内联的。但是,如果它确实有所作为,似乎 in 参数应该在任何地方使用(只读引用有意义的任何地方,即),因为它们提供了速度奖励,并且与ref 不同和out,不需要用户在传递对象时预先添加这些关键字。这将允许更有效地传递值类型对象,而无需对方法和运算符的用户进行任何更改。

总的来说,这可能超出了大多数 C# 开发人员担心的那种小规模优化,但我很好奇它是否有效果。

【问题讨论】:

Point 是一个值类型,所以 in 在这里并没有什么区别。 这是因为操作符一般都是内联的吗?因为通常这会产生通过引用而不是值传递的区别。 @500-InternalServerError in 几乎只对值类型有用。是什么让您认为 in 与值类型一起使用时毫无意义。 @SeanM。您似乎高估了通过引用传递值的好处。除非值类型特别大,否则其他人正在对其进行变异而您实际上想观察这些变异,否则不会有太多收获。如果你的结构设计得很好,也就是说,它们没有明显大于引用的大小,那么通过引用将相当于复制值。对于设计不佳的值类型(或这些指南例外的极少数情况)来说,这确实是一种胜利。 我猜这些准则与常规方法完全相同:如果结构足够大,那么使用“in”是有意义的。 “足够大”是什么意思是另一个问题。 【参考方案1】:

这是否真的有功能上的区别...我最初的想法是没有区别,特别是如果操作符是内联的

由于运算符== 重载在MSIL 中像常规静态方法一样被调用,因此它具有功能差异。它可以帮助避免像常规方法那样不必要的复制。

有什么特别的理由鼓励或不鼓励使用 in 与运算符参数。

根据this article,建议在值类型大于System.IntPtr.Size时应用in修饰符。但重要的是值类型应为 readonly struct。否则in 修饰符会损害性能,因为编译器会在调用结构体的方法和属性时创建一个防御性副本,因为它们可以改变参数的状态。

【讨论】:

以上是关于C# 7.2 对运算符使用“in parameter”的主要内容,如果未能解决你的问题,请参考以下文章

在哪个 .Net Framework 版本 C# 7.2 可用

无法在此 ref ClassName (byRef) 方法上使用类功能 C# 7.2

Visual Studio 2017 使用 C# 7.2 发布 ASP.NET Core 应用程序

C# 7.1 和 7.2 Span 和 ReadOnlySpan

7.2 有序表查找

C# 7.2 代理“按值返回”