因此,我(认为我)了解in
参数修饰符的作用。但是它的作用似乎是多余的。
通常,我认为使用a的唯一原因ref
是修改调用变量,明确禁止使用in
。因此,按in
引用传递在逻辑上似乎等效于按值传递。
有某种性能优势吗?我认为,在事物的后端,ref
参数必须至少复制变量的物理地址,该地址的大小应与任何典型对象引用的大小相同。
因此,那么优势是仅在较大的结构中出现,还是在后台进行了一些编译器优化,使其在其他地方有吸引力?如果是后者,为什么我不应该将每个参数都设为in
?
因此,我(认为我)了解in
参数修饰符的作用。但是它的作用似乎是多余的。
通常,我认为使用a的唯一原因ref
是修改调用变量,明确禁止使用in
。因此,按in
引用传递在逻辑上似乎等效于按值传递。
有某种性能优势吗?我认为,在事物的后端,ref
参数必须至少复制变量的物理地址,该地址的大小应与任何典型对象引用的大小相同。
因此,那么优势是仅在较大的结构中出现,还是在后台进行了一些编译器优化,使其在其他地方有吸引力?如果是后者,为什么我不应该将每个参数都设为in
?
It means that you should never pass a non-readonly struct as in parameter.
Answers:
in
最近被引入C#语言。
in
实际上是一个ref readonly
。一般而言,只有一种用in
例会有所帮助:处理大量readonly struct
s的高性能应用程序。
假设您有:
readonly struct VeryLarge
{
public readonly long Value1;
public readonly long Value2;
public long Compute() { }
// etc
}
和
void Process(in VeryLarge value) { }
在那种情况下,VeryLarge
当在Process
方法中使用该结构时(例如,调用时value.Compute()
),该结构将按引用传递而不创建防御性副本,并且编译器确保了结构的不变性。
请注意,传递struct
带有in
修饰符的非只读将导致编译器在调用struct的方法并访问上述方法中的属性时创建防御性副本Process
,这会对性能产生负面影响!
我建议您仔细阅读一个非常好的MSDN博客条目。
如果您想了解-介绍的更多历史背景in
,可以在C#语言的GitHub存储库中阅读此讨论。
一般而言,大多数开发人员都认为引入in
可能会被视为错误。这是一种非常奇特的语言功能,仅在高性能的情况下才有用。
ref
,例如通过允许someProc(in thing.someProperty);
vs propType myProp = thing.someProperty; someProc(ref myProp);
?是in
仅C#的概念out
,还是已添加到.NET Framework?
in
,因为in
它实际上ref
具有特殊属性。因此,您的第一个代码段将无法编译。@VisualMelon,是的,防御性复制发生在调用方法或从将结构作为参数的方法内部访问结构的属性时。
in
和out
都是从一开始就应该在框架中的概念(以及方法和属性可以指示它们是否被修改的手段this
)。编译器可以in
通过将引用传递给临时保存该属性的属性来允许将属性传递给该参数。如果用另一种语言编写的功能修改了该临时功能,则语义会有些刺耳,但这是功能行为与其签名不匹配的错误。
从
in
逻辑上看,按引用传递等效于按值传递。
正确。
有某种性能优势吗?
是。
我认为,在事物的后端,
ref
参数必须至少复制变量的物理地址,该地址的大小应与任何典型对象引用的大小相同。
没有一个需求,要一个对象的引用和参考的变量都为相同的大小,并且没有一个要求,要么是一个机器字的大小,但是,在实践中都在32 32位位机器和64位机器上的64位。
您认为“实际地址”与之相关的事情对我来说还不清楚。在Windows上,我们在用户模式代码中使用虚拟地址,而不是物理地址。我很奇怪地知道,在什么可能的情况下,物理地址在C#程序中是有意义的。
也不需要将任何类型的引用实现为存储器的虚拟地址。在CLI规范的一致实现中,引用可能是GC表中的不透明句柄。
优势只是在更大的结构中吗?
减少通过较大结构的成本是该功能的推动方案。
请注意,不能保证in
实际上会使任何程序变快,并且会使程序变慢。 关于性能的所有问题都必须通过经验研究来回答。只有很少的优化总是可以取胜的; 这不是“永远获胜”的优化。
是否有一些幕后的编译器优化使其在其他地方有吸引力?
如果这样做不会违反C#规范的规则,则允许编译器和运行时进行任何选择的优化。据我所知,还没有针对in
参数的这种优化,但是这并不排除将来的这种优化。
为什么不应该将每个参数都设为in?
好吧,假设您创建了一个int
参数而不是一个in int
参数。收取什么费用?
假设它是a,double
而您将其更改为in double
。同样,现在无法将变量注册到高性能浮点寄存器中。这不仅影响性能,还可能改变程序性能!允许C#进行高于64位精度的浮点运算,通常只有在可以注册浮点时才这样做。
这不是免费的优化。您必须对照其他方案评估其性能。最好的选择是,首先不要像设计指南所建议的那样首先构建大型结构。
in
真的等同于价值在所有情况下传球?如果我们有f(ref T x, in T y)
并进行f
修改x
,则y
在调用时应该观察到与相同的更改f(ref a,a)
。如果f
接受in T y
和会y
在调用时进行修改的委托,则同样适用。没有in
,语义会有所不同,因为y
我认为它的价值永远不会改变,因为它会是一个副本。
in
是“按引用通,只读”来表示的概念,它在逻辑上等同于由值传递时表现明智。
有。传递a时struct
,in
关键字允许进行优化,其中编译器仅需要传递一个指针,而不会冒该方法更改内容的风险。最后一点很关键-避免了复制操作。在大型结构上,这可以带来很大的不同。
ref
用于通过引用传递结构,而不是复制它们。in
表示不应修改该结构。