结构 - 尽可能快地更改值

时间:2012-02-21 16:00:16

标签: c# constructor struct setter

想象一下,我有一个带X和Y坐标的Point结构。 现在我有构造函数:Point(int x,int y)。

问题:我是否还应该添加名为Point.SetXY(int x,int y)的方法?

示例:

// I have some point
point = new Point (5,5);

// and I wanna change some values
point = new Point (7,7);

// or maybe should I do like this?
point.SetXY (7,7); // is it faster?

对于类我知道它更快,因为你不需要在堆等上创建新实例。

但也许对结构来说无关紧要?

3 个答案:

答案 0 :(得分:4)

除非有很好的理由,否则我建议你的结构不可变 - 只需在需要时创建一个带有新X和Y值的新结构。

举例说明为什么可变结构可能违反直觉(或evil(取决于与创意许可相关的指标))Eric Lippert对该主题有a very good blog post

答案 1 :(得分:2)

我认为你可以通过

来实现它
point.X = 7;
point.Y = 7;

这是最快的

答案 2 :(得分:1)

暴露田野的结构不是邪恶的。虽然一些非常古老的编译器会接受如下代码:

List<Point> myList;
myList[4].X = 5;

将myList [4]复制到临时结构,修改该临时结构的字段X,然后抛弃修改后的结构,并使结构不可变是确保编译器在上述结构中发出尖叫的一种方法,确保编译器在此类代码中发出尖叫声的更好方法是更改​​编译器以禁止写入临时结构的字段。鉴于这些代码已被编译器长期禁止,具有暴露字段的结构通常是保存具有固定数量的独立数据项(例如,点,矩形等)的最佳方式。

什么是有问题的结构,其中除了构造函数或属性设置器之外的函数修改this。虽然编译器会认识到对someStructProperty.someField的写入正在尝试修改someStructProperty,并且在这种修改实际上不起作用的情况下会禁止它,但遗憾的是编译器无法知道{ {1}}将尝试修改结构的临时实例。因此编译器将允许这样的代码,即使它实际上不能按预期工作。在函数应该“就地”修改结构的情况下,我建议作为一种补救方法,即定义一个静态方法,该方法将结构的实例作为someStructProperty.MutatingFunction()参数。例如,ref。编译器会将结构作为SetPointXY(ref Point pt, int x, int y)参数传递视为尝试修改该结构,并且只允许它在实际工作的情况下使用。

请注意,从性能的角度来看,单独编写struct字段的唯一时间不是更新结构的最快方法,那就是当大多数struct匹配默认值或其他一些预先存在的时候结构。可能有一些这样的情况,用预先存在的实例覆盖结构会更快,然后编写应该保存不同内容的字段,但一般情况下我建议只应使用方法或函数来更新结构这样做的代码比单独设置字段的代码更具可读性。如果refAreaCode类型的公共字段,则PhoneNumber的效果远比somePhoneNumber.AreaCode = "847";的效果更清晰。除其他事项外,人们必须研究整个结构,以了解后者是否会改变somePhoneNumber = new PhoneNumber("847", somePhoneNumber.Exchange, somePhoneNumber.Number, somePhoneNumber.Extension);以外的任何字段。另一方面,如果一个人的目标实际上是一个空白的结构,除了一些全新的数据,使用构造函数或工厂方法可能有助于弄清楚一个人这样做的事实;如果只是单独覆盖结构的所有字段,就必须研究整个结构,以便知道没有任何字段可以保持不变。