C#:我应该使用或参考这个结构吗?

时间:2011-04-03 14:00:55

标签: c# performance struct

我不确定提出这个问题的最好方法,所以我先从一个例子开始:

public static void ConvertPoint(ref Point point, View fromView, View toView) {
    //Convert Point
}

此调用是递归的。你传入一个点,它相对于fromView将它转换为相对于toView(只要一个是另一个的祖先)。

该呼叫是递归的,一次将该点转换为一个级别。我知道,可变结构是坏的,但我使用可变点的原因是我只需要创建一个单点并将其传递给递归调用,这就是为什么我使用ref。这是正确的方法,还是使用out参数更好,或者只是声明方法返回一个点?

在这些情况下,我不太熟悉如何处理结构体而不是类。这是从Java移植的代码,其中显然必须是一个类,所以一遍又一遍地使用相同的临时点而不是创建一个必须在每次调用时都被垃圾收集的新点是有意义的。

这可能是一个令人困惑的问题,并且为了更多的混乱,当我在它时,我应该保留一个临时的静态Point实例以进行快速转换,或者它是否就像创建一样简单调用此方法时的新点(称为 lot )?

5 个答案:

答案 0 :(得分:8)

在处理像Point这样的短期对象时,对于垃圾收集器的烦恼绝不是一个错误,假设它实际上是一个类。鉴于这是C#,它可能是一个结构,不超过16个字节。在这种情况下,您应始终编写方法以返回Point。这在运行时得到优化,结构适合cpu寄存器。

只有当它们很大时才考虑通过ref传递结构。

答案 1 :(得分:1)

我倾向于把一切都变成一个简化事物的课程。如果您发现这会在应用程序中产生不必要的内存压力,那么您是否应该研究涉及可变结构的解决方案。

我说这个的原因是GC倾向于非常善于围绕应用程序的需求优化集合,并且可变结构是一个臭名昭着的头痛。如果GC可以处理多个物体的记忆压力,请不要引入头痛。

答案 2 :(得分:1)

取决于你在做什么,以及你为什么这样做。

C#中的结构类似于Java 中的类。就速度和语义而言,它们就像原始类型一样。 (实际上,原始类型在某种意义上是结构。)传递它们确实没有成本,所以如果这是针对尚未出现问题的优化,我建议你只需要制作方法返回Point

然而,在某些情况下,如果struct很大,那么传递结构副本的传递将会更慢,如果此方法是瓶颈,那么 em>,可能是因为你每秒呼叫很多次(我怀疑是这种情况);在这些情况下,通过引用传递它们是有意义的,但首先你需要弄清楚它是否真的是第一个瓶颈。

请注意,例如,在Microsoft的XNA库中,Matrix结构体具有相同方法的两个版本:

static void CreateLookAt(
ref Vector3 cameraPosition, ref Vector3 cameraTarget, ref Vector3 cameraUpVector,
    out Matrix result)

static Matrix CreateLookAt(
    Vector3 cameraPosition, Vector3 cameraTarget, Vector3 cameraUpVector)

这纯粹是出于性能原因,但仅仅是因为这种方法每秒被称为多次次,而Vector3有点更大正常struct

那你为什么要这样做呢?答案取决于你之所以这样写它的原因,但对于典型的代码,它应该没关系。

答案 3 :(得分:1)

结构应该是不可变的,所以我会投票从方法中返回一个不同的点。如果你需要可变性,那么你应该把它变成一个类并在类上创建一个方法来转换它。后者的副产品可能是将递归下降转换为转换的迭代应用。

答案 4 :(得分:0)

由于这是一个结构,我认为在这里使用ref没有任何好处。无论如何它都会在堆栈上多次复制,所以为什么不回复呢?我认为如果使用Point声明此方法作为返回类型,它将使代码更具可读性。