如何最好地修改和返回C#参数?

lan*_*nce 5 c# return-type signatures

我需要一个已经设置了几个属性值的Widget.我需要更改Widget的名称.我被选为第3选项,但我很难说清楚原因.

public void Do(Widget widget) { // 1
    widget.Name = "new name";
}

public void Do(ref Widget widget) { // 2
    widget.Name = "new name";
}

public Widget Do(Widget widget) { // 3
    widget.Name = "new name";
    return widget;
}
Run Code Online (Sandbox Code Playgroud)

我想和几个问题一起玩Devil's Advocate并收集回复,以帮助我解释为什么我被选项3所吸引.

选项1:为什么修改传入的Widget?你只是"返回"一个对象.为什么不直接使用传入的对象?

选项2:为什么返回无效?为什么不在签名中传达您将使用实际的内存指针到参数对象本身?

选项3:你返回的是你传入的同一个物体,这不奇怪吗?

Bro*_*ass 12

选项1:这是最常用的方法 - 如果您不想修改引用本身,则不需要引用.确保您正确命名您的方法,以期望传递的对象确实被修改.

选项2:这仅在您想要更改传递的引用本身时才有用,即创建新Widget实例或将引用设置为指向现有窗口小部件(如果您希望将所有实例的总数保持在较低水平,则这可能很有用具有相同的属性,请参阅Flyweight模式,通常返回的小部件在这种情况下应该是不可变的,而您将使用工厂代替).在你的情况下,这似乎不合适.

选项3:这允许流畅的"构建者"方法 - 也有其好处,即对Widget的更改链接,一些人认为更具表现力和自我记录.另见Fluent界面


Cod*_*aos 6

选项1:

精细.正是我用的东西.您可以改变窗口小部件的内容,但不能改变窗口小部件本身.

选项2:

不行号.您不需要修改参考号,因此您无需使用ref.如果您修改了引用本身(例如,widget = new Widget()那么out/ ref是正确的选择,但根据我的经验,很少需要.

选项3:
与选项1类似.但可以用流畅的样式API链接.我个人不喜欢这个.如果我返回副本并保持原始对象不变,我只使用该签名.


但最重要的是你如何命名方法.名称需要明确暗示原始对象是变异的.

在许多情况下,我会选择选项4:使类型不可变并返回副本.但是,对于显然是实体而非价值的小部件,这没有任何意义.

  • @David如果widget是引用类型,它将修改窗口小部件的内容.你所说的只适用于结构/值类型,而且在C#中使用小部件类型的人是疯了. (2认同)