修改引用类型参数的方法不好吗?
我见过这样的方法:
public void Foo(List<string> list)
{
list.Add("Bar");
}
Is this goodpractice tomodifyparametersinamethod?
这样不是更好吗?
public List<string> Foo(List<string> list)
{
// Edit
List<string> newlist = new List<string>(list);
newlist.Add("Bar");
return newlist;
}
感觉第一个例子有意想不到的副作用。
I've seen methods like this:
public void Foo(List<string> list)
{
list.Add("Bar");
}
Is this good practice to modify parameters in a method?
Wouldn't this be better?
public List<string> Foo(List<string> list)
{
// Edit
List<string> newlist = new List<string>(list);
newlist.Add("Bar");
return newlist;
}
It just feels like the first example has unexpected side effects.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
在您给出的示例中,第一个对我来说似乎比第二个好得多。 如果我看到一个接受列表并返回列表的方法,我的第一个假设是它返回一个新列表并且不触及给定的列表。 因此,第二种方法具有意想不到的副作用。
只要你的方法命名得当,修改参数就没有什么危险。 考虑一下:
使用“Fill”这样的名称,您可以非常确定该方法将修改列表。
In the example you've given, the first seems a lot nicer to me than the second. If I saw a method that accepted a list and also returned a list, my first assumption would be that it was returning a new list and not touching the one it was given. The second method, therefore, is the one with unexpected side effects.
As long as your methods are named appropriately there's little danger in modifying the parameter. Consider this:
With a name like "Fill" you can be pretty certain that the method will modify the list.
坦率地说,在这种情况下,两种方法或多或少都做相同的事情。 两者都会修改传入的
List
。如果目标是通过这种方法使列表不可变,则第二个示例应该复制发送的
List
中,然后对新的List
执行Add
操作,然后返回该操作。我不熟悉 C# 也不熟悉 .NET,所以我的猜测是:
这样,调用
Foo
方法的方法将获得新创建的List 返回,传入的原始
List
不会被触及。这实际上取决于您的规范或 API 的“合同”,因此在可以修改 List 的情况下,我认为使用第一种方法没有问题。
Frankly, in this case, both methods do more or less the same thing. Both will modify the
List
that was passed in.If the objective is to have lists immutable by such a method, the second example should make a copy of the
List
that was sent in, and then perform theAdd
operation on the newList
and then return that.I'm not familiar with C# nor .NET, so my guess would be something along the line of:
This way, the method which calls the
Foo
method will get the newly createdList
returned, and the originalList
that was passed in would not be touched.This really is up to the "contract" of your specifications or API, so in cases where
List
s can just be modified, I don't see a problem with going with the first approach.您在两种方法中执行完全相同的操作,只是其中一种方法返回相同的列表。
在我看来,这实际上取决于你在做什么。 只要确保您的文档清楚说明正在发生的事情即可。 如果您喜欢这类事情,请编写前置条件和后置条件。
You're doing the exact same thing in both methods, just one of them is returning the same list.
It really depends on what you're doing, in my opinion. Just make sure your documentation is clear on what is going on. Write pre-conditions and post-conditions if you're into that sort of thing.
使用列表作为参数的方法修改列表实际上并不意外。 如果你想要一个只从列表中读取的方法,你可以使用一个只允许读取的接口:
通过使用这样的接口,你不仅禁止该方法更改列表,而且它还变得更加灵活,因为它可以使用任何实现该接口的集合,例如字符串数组。
其他一些语言具有 const 关键字,可以将其应用于参数以禁止方法更改它们。 由于 .NET 具有可用于此目的的接口和不可变的字符串,因此实际上不需要
const
参数。It's actually not that unexpected that a method that takes a list as parameter modifies the list. If you want a method that only reads from the list, you would use an interface that only allows reading:
By using an interface like this you don't only prohibit the method from changing the list, it also gets more flexible as it can use any collection that implements the interface, like a string array for example.
Some other languages has a
const
keyword that can be applied to parameters to prohibit a method from changing them. As .NET has interfaces that you can use for this and strings that are immutable, there isn't really a need forconst
parameters.扩展方法的出现使得处理引入副作用的方法变得更加容易。 例如,在您的示例中,说出
和调用它
变得更加直观,这使得列表中发生的事情变得更清楚。
正如评论中提到的,这在列表上最有用,因为对列表的修改往往会更加混乱。 对于一个简单的对象,我倾向于只就地修改对象。
The advent of extension methods has made it a bit easier to deal with methods that introduce side effects. For example, in your example it becomes much more intuitive to say
and call it with
which makes it clearer that something is happening to the list.
As mentioned in the comments, this is most useful on lists since modifications to a list can tend to be more confusing. On a simple object, I would tend to just to modify the object in place.