gpt4 book ai didi

c# - 具有原始值类型的 "in"修饰符?

转载 作者:太空宇宙 更新时间:2023-11-03 20:53:24 31 4
gpt4 key购买 nike

我读过 article在 MSDN 上。它解释了为什么“in”应该只与自定义只读结构一起使用,否则会有性能损失。但是,我不太明白如何对原始类型使用“in”。由于 C# 中的所有内置值类型都是不可变的,这是否意味着与按值传递它们相比,使用“in”修饰符按引用传递它们会略微提高性能?

例子:

public class Product
{
private readonly int _weight;
private readonly decimal _price;

public Product(in decimal price, in int weight)
{
_price = price;
_weight = weight;
}
}

对比

public class Product
{
private readonly int _weight;
private readonly decimal _price;

public Product(decimal price, int weight)
{
_price = price;
_weight = weight;
}
}

最佳答案

in 修饰符通过在调用方法时避免不必要的值类型副本来提高性能。请注意,值类型(即结构)实际上并不是自动不可变的(但 C# 编译器确实通过制作“防御性副本”然后在设置属性值时覆盖整个父 struct 来提供不可变的外观,这在您链接到的文章中有解释)。

鉴于如果您不使用 in(或 out/ref),结构将在方法调用中被完整复制,您可以通过仅将指针传递给调用堆栈中更高层的结构对象来提高性能,因为指针(.NET 中的引用)小于结构,但这只是在结构也是真正不可变的情况下避免复制.

C# 的内置值类型(Int16Int32DoubleUInt64 等)是都小于(或相同大小)64 位系统上的指针(Decimal 是 128 位类型,String 是引用类型),这意味着对这些类型使用 in 修饰符的好处为零。您还将因产生指针取消引用的成本而遭受性能损失 - 这也可能导致处理器 memory cache miss .

考虑下面的一些不同场景(所有示例都假设 x64,并且没有更改方法调用语义或调用约定的优化):

传递一个小值类型

public static void Main()
{
Int32 value = 123; // 4 bytes
Foo( in value ); // Get an 8-byte pointer to `value`, then pass that
}

public static void Foo( in Int32 x ) { ... }

性能受到影响,因为现在计算机正在传递一个也需要取消引用的 8 字节指针值,而不是可以立即使用的 4 字节值。

传递大值类型

public struct MyBigStruct
{
public Decimal Foo;
public Decimal Bar;
public Decimal Baz;
}

public static void Main()
{
MyBigStruct value; // 48 bytes
Foo( in value ); // Get an 8-byte pointer to `value`, then pass that
}

public static void Foo( in MyBigStruct x ) { ... }

可能会提高性能,因为计算机正在传递 8 字节指针值而不是复制 48 字节值,但是指针取消引用可能比复制额外的 32 字节更昂贵.您应该在运行时分析以确定更改是否值得。这也使得 Foo 中的 x 不可变,否则 Main 中的 value 将被修改。

关于c# - 具有原始值类型的 "in"修饰符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53012473/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com