C# 就地更改值,而不是创建新实例

C# 就地更改值,而不是创建新实例,c#,.net,performance,C#,.net,Performance,基本上我已经检查了xna和一些slimdx(Promit:),它们有很多结构。几乎所有的方法都是这样的: public static Vector3 operator + ( Vector3 a, Vector3 b ) 在哪里做类似的事情: Vector3 c = new Vector3 ( ... ) 我想知道这样做是否有意义: a.X += b.X ... return a 显然#1看起来更合理/合理,但#2无法创建更快的新矢量3 我认为它很快也很清晰,如果不是像#1那样清晰的话

基本上我已经检查了xna和一些slimdx(Promit:),它们有很多结构。几乎所有的方法都是这样的:

public static Vector3 operator + ( Vector3 a, Vector3 b )
在哪里做类似的事情:

Vector3 c = new Vector3 ( ... )
我想知道这样做是否有意义:

a.X += b.X
...

return a
显然#1看起来更合理/合理,但#2无法创建更快的新矢量3

我认为它很快也很清晰,如果不是像#1那样清晰的话


哪一个更好?#2有什么问题吗

我真的怀疑您是否需要如此担心性能,以至于需要这样做。做#1


“过早优化是万恶之源。”-Donald Knuth的唯一问题是,由于Vector3是一种值类型(出于充分的理由,请参阅以了解详细信息),因此当它们是集合的一部分或用作属性成员时,您无法进行在位编辑

例如,拥有列表成员是很常见的,但如果您有:

myList[150].X += ...;

它失败了,因为索引器返回一个新的结构(值类型语义)。对于值类型来说,通常更安全的做法是将它们视为不可变的,这需要您的第一个语法。

如果他正在开发游戏和图形应用程序,性能比典型的商业应用程序更重要。@Reed-但您仍然应该分析并找出实际的瓶颈。如果是在其他地方,优化这一点是没有帮助的。Knuth没有说“过早优化商业应用程序是万恶之源。”;你会注意到那里没有资格证书。一旦你的个人资料,你会发现你的慢下来的地方;在此之前,您只是在猜测,几乎可以肯定会大幅降低代码质量。@Mark-是的,但我们不应该使用Knuth的引用来假装性能问题不存在。对于360上使用XNA的游戏,垃圾收集通常是一件大事,避免垃圾收集的编程习惯是首选。是的,我正在开发实时游戏和3d应用程序,对我来说,每一秒都很重要。但是我知道一个特定的优化对于它带来的收益来说是非常不现实的。但对于这个案例来说,这是非常重要的,我个人不认为2比1更复杂。我想我把问题的标题写错了。我的意思是更改传递的值,即不是原始值,而是通过引用传递的副本。琼:通常,将值类型视为不可变的是一个好主意(.net设计指南甚至建议为此创建对象类)。Vector3通常不会出现在游戏中,但这是为了方便起见。第二种语法仅在类型是可变的情况下有效,我尽量避免使用它,因为它“看起来”像引用类型。性能。明智地说,在JIT到达它们之后,它们通常是相同的(尽管特定的情况可能不同)。您能详细说明一下如何在方法中充分使用它们吗?然后我可以根据我的经验给你一些建议(我是一个使用C#-的全职3D开发人员,所以这是我的拿手好戏。)嘿,里德,谢谢你的帮助。我知道可变结构不受欢迎,但当我第一次在xna和slimdx上看到它时,我就有了这个想法。我可能会使它们不可变,所以它可能是无效的。但是可变结构,基本上这些操作符是重载的,然后调用a+b,c+d等等。只是#1将创建一个新的额外值来返回。但是这个值将通过ref传递,所以再次复制,对吗?琼:因为这些都是值类型,新对象将在堆栈上创建,并在返回时通过值复制。如果将“a”视为可变的,则还需要在方法返回时复制它。由于您使用的是值类型,所以差异非常小。对于引用类型,这会有所不同,但是执行#2会在调用方端更改“a”,这会产生副作用,因此您也应该避免使用它。理论上,您可以通过直接返回“a”来保存一个堆栈分配,但这里有一个副作用。