Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.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#_.net_Optimization_Class Design - Fatal编程技术网

在C#中通过引用将结构值传递给方法是可接受的优化吗?

在C#中通过引用将结构值传递给方法是可接受的优化吗?,c#,.net,optimization,class-design,C#,.net,Optimization,Class Design,假设我有一个结构: struct MyStruct { public int X public int Y } 以及某个类中在其他地方多次迭代的方法: public bool MyMethod( MyStruct myStruct ) { return ... } 将MyMethod签名更改为以下内容是否是可接受的优化 public bool MyMethod( ref MyStruct myStruct ) 如果是这样的话,它到底有多大的优势?如果不是,那么使用r

假设我有一个结构:

struct MyStruct
{
    public int X
    public int Y
}
以及某个类中在其他地方多次迭代的方法:

public bool MyMethod( MyStruct myStruct )
{
    return ...
}
将MyMethod签名更改为以下内容是否是可接受的优化

public bool MyMethod( ref MyStruct myStruct )

如果是这样的话,它到底有多大的优势?如果不是,那么使用
ref
这种方式,一个结构需要多少字段才能获得足够大的优势?

在32位系统上,您将更改为推送8字节而不是4字节的数据。在64位系统上推送的数据量没有变化。您还向编译器/JITter添加了一个要求,即结构必须存在于内存中,因为您将获取它的地址,这可能会否定其他优化

我怀疑这将显示您的程序中有任何性能提升。首先进行概要分析,看看MyMethod是否是程序中的瓶颈


然后,假设MyMethod中没有其他优化机会,将其更改为pass by ref,然后再次配置文件以查看是否有任何改进。

使用两个
int
字段,优势将非常小,不太可能有什么不同。这可能根本没什么区别


一旦开始添加两个以上的整型字段,这种优势就开始增加。不过,除非您经常调用该方法,否则这还不够重要。

因为您明确询问该方法是否“可接受”

我的回答是否定的。通过
ref
传递参数,你在对编译器和程序员撒谎ref(独占)表示您打算修改方法内部的参数

当然,您可以向程序员(但不向编译器…)提供解释“谎言”的附加注释。但是为什么首先滥用语义呢


如果你真的需要这种极端的微优化(看看其他答案——任何性能优势都是值得怀疑的,原因有很多!)。NET可能就是一个错误的环境。给出C++中的相关部分,

,不可能,举个例子。在64位处理器上,该结构可以轻松地装入寄存器,而不会通过堆栈。尽管不是在32位处理器和实例方法上。当您通过引用传递时,您需要为访问结构成员付费,需要额外的指针取消引用。这可能会比避免复制更昂贵,ymmv

当结构超过16字节时,通常开始支付。当结构变大时,通用指南切换到类的一个原因是。考虑到这完全取决于使用情况,您要么分析代码并阅读程序集(当然是发布版本),要么使用探查器。探查器不太可能显示出差异。通常很难测量纳秒,除非你人工测量十亿次。

一般来说,我会说不:坚持使用具有属性的类。然而,在某些情况下,可能需要这样做——特别是在紧凑框架(想想:XNA)或微框架上。在这两种情况下,GC都非常不同,对象分配(和非确定性集合)可能会对应用程序产生重大影响

在这种情况下,看到更多的结构发挥作用并非闻所未闻,而且
ref
避免了常见的“丢失更新”问题(在大多数.NET中,结构应该是不可变的;同样,XNA也有一些场景使其很容易打破这一规则)。当然,另一种方法是接受并返回数据——然后类型可以是不可变的


如果你指的是通过物体的表现;然后,您必须对您打算使用的确切设置进行配置。x86和x64是明显的区别,但还有更多的区别。例如,使用
ref
要求一个值位于字段或局部变量中,但结构上的许多JIT性能调整都在堆栈的顶部工作,这意味着可能会有比严格需要的更多的“ldloc”/“stloc”。你还引入了一个额外的解引用。

如果有人问关于性能的理论问题,为什么每个人都会说“配置文件优先”或“过早优化是万恶之源”?@Rauhotz:因为“理论”和“性能”在同一句话里真的是一个非-sequitur@Rauhotz:因为这些事情很多都取决于情况:某个东西被调用了多少次,什么是操作系统,什么是环境。垃圾收集器在不同情况下的行为不同。有时占用更多内存根本不是问题,有时是不好的,这取决于程序运行的位置和运行的其他内容。改进的努力总是与你所拥有的时间相平衡的。