修改引用类型参数的方法不好吗?

发布于 2024-07-14 20:39:46 字数 418 浏览 12 评论 0原文

我见过这样的方法:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

莫多说 2024-07-21 20:39:46

在您给出的示例中,第一个对我来说似乎比第二个好得多。 如果我看到一个接受列表并返回列表的方法,我的第一个假设是它返回一个新列表并且不触及给定的列表。 因此,第二种方法具有意想不到的副作用。

只要你的方法命名得当,修改参数就没有什么危险。 考虑一下:

public void Fill<T>(IList<T> list)
{
    // add a bunch of items to list
}

使​​用“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:

public void Fill<T>(IList<T> list)
{
    // add a bunch of items to list
}

With a name like "Fill" you can be pretty certain that the method will modify the list.

暮光沉寂 2024-07-21 20:39:46

坦率地说,在这种情况下,两种方法或多或少都做相同的事情。 两者都会修改传入的 List

如果目标是通过这种方法使列表不可变,则第二个示例应该复制发送的 List中,然后对新的 List 执行 Add 操作,然后返回该操作。

我不熟悉 C# 也不熟悉 .NET,所以我的猜测是:

public List<string> Foo(List<string> list)
{
    List<string> newList = (List<string>)list.Clone();
    newList.Add("Bar");
    return newList;
}

这样,调用 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 the Add operation on the new List and then return that.

I'm not familiar with C# nor .NET, so my guess would be something along the line of:

public List<string> Foo(List<string> list)
{
    List<string> newList = (List<string>)list.Clone();
    newList.Add("Bar");
    return newList;
}

This way, the method which calls the Foo method will get the newly created List returned, and the original List that was passed in would not be touched.

This really is up to the "contract" of your specifications or API, so in cases where Lists can just be modified, I don't see a problem with going with the first approach.

如歌彻婉言 2024-07-21 20:39:46

您在两种方法中执行完全相同的操作,只是其中一种方法返回相同的列表。

在我看来,这实际上取决于你在做什么。 只要确保您的文档清楚说明正在发生的事情即可。 如果您喜欢这类事情,请编写前置条件和后置条件。

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.

久光 2024-07-21 20:39:46

使用列表作为参数的方法修改列表实际上并不意外。 如果你想要一个只从列表中读取的方法,你可以使用一个只允许读取的接口:

public int GetLongest(IEnumerable<string> list) {
    int len = 0;
    foreach (string s in list) {
        len = Math.Max(len, s.Length);
    }
    return len;
}

通过使用这样的接口,你不仅禁止该方法更改列表,而且它还变得更加灵活,因为它可以使用任何实现该接口的集合,例如字符串数组。

其他一些语言具有 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:

public int GetLongest(IEnumerable<string> list) {
    int len = 0;
    foreach (string s in list) {
        len = Math.Max(len, s.Length);
    }
    return len;
}

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 for const parameters.

绅士风度i 2024-07-21 20:39:46

扩展方法的出现使得处理引入副作用的方法变得更加容易。 例如,在您的示例中,说出

public static class Extensions
{
  public static void AddBar(this List<string> list)
  {
     list.Add("Bar");
  }
}

和调用它

mylist.AddBar();

变得更加直观,这使得列表中发生的事情变得更清楚。

正如评论中提到的,这在列表上最有用,因为对列表的修改往往会更加混乱。 对于一个简单的对象,我倾向于只就地修改对象。

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

public static class Extensions
{
  public static void AddBar(this List<string> list)
  {
     list.Add("Bar");
  }
}

and call it with

mylist.AddBar();

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文