Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/290.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在循环中无休止地创建结构是否会影响性能或产生其他副作用?_C# - Fatal编程技术网

C# 在循环中无休止地创建结构是否会影响性能或产生其他副作用?

C# 在循环中无休止地创建结构是否会影响性能或产生其他副作用?,c#,C#,我在查看一些代码,他们基本上有: while (true) // update loop { someStruct = new SomeStruct(1,2); } 在循环中创建这样的对象是不好的,您应该创建它一次,然后更新它,以避免创建/销毁数以百万计的对象 但这不是问题: while (true) // update loop { x = x + 1; } 因为x是一种值类型。但是结构也有点类似于值类型。它们显然不受垃圾收集的影响 所以现在我想知道在循环中创建结构是否会带来性

我在查看一些代码,他们基本上有:

while (true) // update loop
{
   someStruct = new SomeStruct(1,2);
}
在循环中创建这样的对象是不好的,您应该创建它一次,然后更新它,以避免创建/销毁数以百万计的对象

但这不是问题:

while (true) // update loop
{
   x = x + 1;
}
因为x是一种值类型。但是结构也有点类似于值类型。它们显然不受垃圾收集的影响

所以现在我想知道在循环中创建结构是否会带来性能成本,或者您是否仍然应该创建一个并更新它(代码可读性/未来证明除外)

所以现在我想知道在循环中创建结构是否会带来性能损失

一如既往的表现;量!正如您所说,它们不会影响垃圾收集,我也不希望出现任何重大的性能问题。然而,从历史上看,c#jitter在其应用的优化方面受到了一定的限制,因此,如果性能是最重要的考虑因素,那么它可能有助于简化操作并编写尽可能简单的代码

或者,如果您仍然需要创建并更新它(代码可读性/未来校对除外)

我认为,就地更新结构可能是个坏主意。看见但这可能取决于您使用的结构有多大,如果出于某种原因您有一个非常大的结构,并且只需要更新一个值,那么最好就地更新它,并解决可变结构的问题。但是,对于性能敏感的场景,您应该避免使用大型结构,除非您了解有关值类型和复制的所有规则

所以现在我想知道在循环中创建结构是否会带来性能损失

一如既往的表现;量!正如您所说,它们不会影响垃圾收集,我也不希望出现任何重大的性能问题。然而,从历史上看,c#jitter在其应用的优化方面受到了一定的限制,因此,如果性能是最重要的考虑因素,那么它可能有助于简化操作并编写尽可能简单的代码

或者,如果您仍然需要创建并更新它(代码可读性/未来校对除外)


我认为,就地更新结构可能是个坏主意。看见但这可能取决于您使用的结构有多大,如果出于某种原因您有一个非常大的结构,并且只需要更新一个值,那么最好就地更新它,并解决可变结构的问题。但是,对于性能敏感的场景,您应该避免使用大型结构,除非您了解有关值类型和复制的所有规则。

它可能会被抖动优化掉。考虑下面的例子,

private struct SomeStruct
{
    public int A;
    public SomeStruct(int a) { A = a; }
}

public void M() {
    SomeStruct s = new SomeStruct(1);
    
    while (true) // update loop
    {
       s = new SomeStruct(s.A + 1);
    }
}
其中,方法M被JIT到:

L0000: push ebp
L0001: mov ebp, esp
L0003: mov eax, 1
L0008: inc eax
L0009: jmp short L0008
将循环替换为

while (true) // update loop
{
   s.A = s.A + 1;
}
产生完全相同的汇编代码


因此,作为结论,我建议使用以下代码(与第一个示例相同,只是将struct字段设置为只读):


它创建与“可变”结构相同的汇编代码,但在编译过程中使用“不可变”结构具有额外的安全性。

它可能会被抖动优化掉。考虑下面的例子,

private struct SomeStruct
{
    public int A;
    public SomeStruct(int a) { A = a; }
}

public void M() {
    SomeStruct s = new SomeStruct(1);
    
    while (true) // update loop
    {
       s = new SomeStruct(s.A + 1);
    }
}
其中,方法M被JIT到:

L0000: push ebp
L0001: mov ebp, esp
L0003: mov eax, 1
L0008: inc eax
L0009: jmp short L0008
将循环替换为

while (true) // update loop
{
   s.A = s.A + 1;
}
产生完全相同的汇编代码


因此,作为结论,我建议使用以下代码(与第一个示例相同,只是将struct字段设置为只读):


它创建的汇编代码与“可变”结构相同,但在编译过程中使用“不可变”结构具有额外的安全性。

相关:这取决于结构是否包含任何引用类型。如果不是,那么整个东西将存在于堆栈上(在您的示例代码中)。如果
someStruct
实际上是一个结构,并且它的构造函数不分配任何存在于堆上的新对象(也称为引用类型),那么这实际上与
x=x+1
语句没有什么不同。。。对Jon Skeet来找你,因为他甚至想建议可变结构:)相关:这取决于结构是否包含任何引用类型。如果不是,那么整个东西将存在于堆栈上(在您的示例代码中)。如果
someStruct
实际上是一个结构,并且它的构造函数不分配任何存在于堆上的新对象(也称为引用类型),那么这实际上与
x=x+1
语句没有什么不同。。。对Jon Skeet来找你,因为他甚至想建议可变结构:)如果“出于某种原因,你有一个非常大的结构”,这是你自己的错,没有阅读指导,实际上没有人应该关心你的代码在这一点上的性能:)(确实有可能存在一个用例,但这类代码的作者应该完全理解这一点上的所有缺陷,并且应该能够在代码审查期间轻松解释所有这些缺陷)@Alexei Levenkov拥有大型结构有一些正当的理由,例如,如果控制内存布局很重要。但这应该是罕见的,并且需要非常小心地使用以避免复制。如果“出于某种原因,您拥有一个非常大的结构”不阅读指南是您自己的错,实际上,在这一点上,没有人应该关心您的代码的性能:)(确实可能有一个用例,但这类代码的作者应该完全理解这一点上的所有缺点,并且应该能够在代码审查期间轻松地解释所有这些)@Alexei Levenkov拥有大型结构有一些合理的理由,例如,如果控制内存布局很重要的话。但它应该是罕见的,并且需要非常小心地使用以避免复制。