记录类型、记忆使用情况和复制操作

Record types, memorry usage and copy operations

提问人:huzzm 提问时间:11/17/2023 最后编辑:huzzm 更新时间:11/18/2023 访问量:45

问:

如果我在 C# 中定义一条记录,例如

public record Pair(int First, int Second);

我有一个循环,我在那里做

Pair x = new(1, 2);
while (...)
{
    x = new(x.First + 1, x.Second + 1);
}

我的 IDE 在以大输入大小执行我的程序后突出显示了那行代码,并告诉我这里分配了很多 (100MB),因为 Pair 类型是不可变的,并且在每次循环迭代中都会创建一个副本(内存分配)。

我的问题是,我可以完全信任这个说法,还是编译器会优化它?

我重写了代码,使 Pair 记录一个类,并提供修改内容的方法,以便在整个程序执行期间只有一个实例处于活动状态。

public class Location
{
    public Location()
    {
        First = 0;
        Second = 0;
    }

    public void Increment() 
    { 
        First++; 
        Second++;
    }

    public int First { get; private set; }
    public int Second { get; private set; }
}

因此,在循环中,我现在可以执行以下操作:

Pair x = new(1, 2);
while (...)
{
    
    x.Increment();
}

但是当我用

var proc = System.Diagnostics.Process.GetCurrentProcess();
Console.WriteLine($"{proc.PrivateMemorySize64/1000000.0}MB");

然后使用的 MB 并没有真正下降,没有明显的差异,这让我感到疑惑。

C# 内存 复制 不可变性

评论

0赞 madreflection 11/18/2023
“我已经重写了代码”......但是你没有展示它,所以我们不能说出其中的差异,我们也无法假设你如何重写它或你如何使用重写的版本。如果您仍在执行相同的循环,则可变或不可变不会产生任何影响,因为您仍在每次迭代中创建一个新实例。
1赞 Marc Gravell 11/18/2023
public record struct Pair(int First, int Second);<=== 繁荣
1赞 madreflection 11/18/2023
不要在评论中告诉我。编辑帖子以包含详细信息。该帖子本身应该是完整的。
1赞 Marc Gravell 11/18/2023
@madreflection副作用: - 更好的;ppublic readonly record struct Pair(int First, int Second);
1赞 madreflection 11/18/2023
@MarcGravell:没错,但我不是在谈论副作用。我说的是直接影响。决定使用值类型而不是引用类型可能会产生意想不到的后果,例如在将值传递给方法时将值复制到堆栈而不是引用所需的额外开销。这是一个微不足道的情况,在 64 位架构上,两个 s 和一个引用的大小是相同的,但关键是它们的工作方式不同,OP 需要牢记这一点。OP的惊讶表明,他们在这方面还有很多东西要学。int

答: 暂无答案