如何最好地修改和返回 C# 参数?
我需要一个已经设置了多个属性值的小部件。我需要更改小部件的名称。我倾向于选项 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;
}
我想玩魔鬼代言人的游戏,提出几个问题并收集答案,以帮助我解释为什么我会选择选项 3。
选项 1:为什么不只是修改传入的 Widget?您只是“返回”一个对象。为什么不直接使用传入的对象呢?
选项 2:为什么不返回 void?为什么不在签名中传达您将使用指向参数对象本身的实际内存指针?
选项 3: 返回与传入的对象相同的对象,你不觉得奇怪吗?
I need to take a Widget that already has several property values set. I need to change the Widget's name. I'm drawn toward Option 3, but I'm having a hard time articulating why.
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;
}
I'd like to play Devil's Advocate with a few questions and gather responses, to help me explain why I'm drawn to Option 3.
Option 1 : Why not just modify the Widget that's passed in? You're only "returning" one object. Why not just use the object that's passed in?
Option 2 : Why not return void? Why not just communicate in the signature that you'll be using the actual memory pointer to the parameter object itself?
Option 3 : Isn't it weird to you that you're returning the same object you're passing in?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
选项 1:这是最常见的方法 - 如果您不想修改引用本身,则不需要 ref。确保正确命名方法,以便期望传递的对象确实被修改。
选项 2:仅当您想要更改传递的引用本身时,这才有用,即创建一个新的
Widget
实例或将引用设置为指向到现有的小部件(如果您希望保持实例总数较低,并且它们都具有相同的属性,这可能很有用,请参阅 享元模式,一般来说在这种情况下,返回的小部件应该是不可变的,您可以使用工厂代替)。就您而言,这似乎不合适。选项 3:这允许流畅的“构建器”方法 - 也有它的好处,即对 Widget 的更改进行链接,有些人认为这更具表现力和自文档化。另请参阅流畅界面
Option 1: This is the most common approach - you do not need ref if you don't want to modify the reference itself. Make sure that you name your method appropriately so the expectation is that the passed object is indeed modified.
Option 2: This is only useful if you want to change the passed reference itself, i.e. create a new
Widget
instance or set the reference to point to an existing widget (this might be useful if you want to keep overall number of instances low if they all have the same properties, see Flyweight pattern, generally the returned widgets should be immutable in this case though and you would use a factory instead). In your case this does not seem appropriate.Option 3: This allows for a fluent "builder" approach - also has its benefits, i.e chaining of changes to the Widget which some people consider more expressive and self-documenting. Also see Fluent interface
选项 1:
很好。正是我要用的。您可以改变小部件的内容,但不能改变小部件本身。
选项 2:
不,不,不。您不会修改引用本身,因此不需要使用
ref
。如果您修改了引用本身(例如widget = new Widget()
,则out
/ref
是正确的选择,但根据我的经验,这是很少需要选项3:
与选项 1 类似。但可以以流畅的 API 方式链接。我个人不喜欢这个。我仅在返回副本并保持原始对象不变时才使用该签名。
但这里最重要的是如何命名该方法。该名称需要清楚地暗示原始对象已发生变异。
在许多情况下,我会选择选项 4:使类型不可变并返回副本。但是对于显然是实体而不是值的小部件,这是没有意义的。
Option 1:
Fine. Exactly what I'd use. You can mutate the content of the widget, but not the widget itself.
Option 2:
No. No. No. You don't modify the reference itself, so you don't need to use
ref
. If you modified the reference itself (for examplewidget = new Widget()
thenout
/ref
are the correct choices, but in my experience that's rarely necessary.Option 3:
Similar to option 1. But can be chained in a fluent style API. Personally I don't like this. I only use that signature if I return a copy and leave the original object untouched.
But the most important thing here is how you name the method. The name needs to clearly imply that the original object is mutated.
In many situations I'd opt for Option 4: Make the type immutable and return a copy. But with widgets which obviously are entity and not value like, this makes no sense.
这三个选项实际上没有任何功能差异。 (存在差异,只是与您的问题无关。)保持简单 - 使用选项 1。
There isn't actually any functional difference between the 3 options. (There ARE differences, just none that are relevant to your question.) Keep it simple - use option 1.
我认为方案1和方案3都是可行的方案。选项 3 的优点是可以自记录,因为它意味着您正在方法中修改 Widget。我认为最糟糕的选择是选项 2。对我来说,
ref
关键字意味着您正在修改对象的引用,而您肯定没有这样做。I think Option 1 and Option 3 are both viable options. Option 3 has the benefit of being self-documenting in that it implies that you are modifying Widget in the method. I think the worst option is Option 2. The
ref
keyword to me implies that you are modifying the reference of the object, which you are most certainly not doing.