2009-03-07 2 views
1

参照型パラメータを変更するメソッドが不正ですか?私はこのような方法を見てきました

public void Foo(List<string> list) 
{ 
    list.Add("Bar"); 
} 

は、メソッドのパラメータを変更するには、このことをお勧めますか?

これは良くありませんか?

public List<string> Foo(List<string> list) 
{ 
    // Edit 
    List<string> newlist = new List<string>(list); 
    newlist.Add("Bar"); 
    return newlist; 
} 

予期しない副作用が最初の例のように感じられます。

+0

私はあなたが言うことを意味すると思います リスト新しいリスト(リスト); –

+0

ありがとうございます。私はそれを更新しました。 –

答えて

7

あなたが指定した例では、最初のものは2番目のものより私にはかなり良いと思われます。リストを受け入れてリストを返すメソッドを見た場合、私の最初の前提は新しいリストを返していて、それが与えられたリストに触れていないということです。したがって、第2の方法は予期しない副作用を伴う方法である。

メソッドの名前が適切であれば、パラメータを変更する危険性はほとんどありません。これを考慮してください:

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

"Fill"のような名前では、メソッドがリストを変更することはかなり確信で​​きます。

+0

2番目の方法でパラメータを変更しないように編集しました。 –

+0

私が持っている問題は、メソッドがパラメータを決して変更しないと予想する癖があることです。どのように私はその習慣に入ったかわからない。 –

+0

あなたはF#を調べるべきです - 機能的なプログラミングがあなたの路地のすぐ上にあるようなサウンド。 –

0

両方のメソッドで全く同じことをしていますが、どちらか一方だけが同じリストを返しています。

私の意見では、実際にあなたがやっていることに依存します。何が起きているのかについてのドキュメントが明確であることを確認してください。あなたがそのようなことをするなら、事前条件と事後条件を書いてください。

+0

2番目の方法でパラメータを変更しないように編集しました。 –

1

この場合、どちらの方法も多かれ少なかれ同じことをします。どちらが渡されたListを変更します。

目的は、このような方法で不変のリストを持っているのであれば、第二の例は、送られてきたListのコピーを作成し、その上Add操作を実行する必要があります新しいListとそれを返します。

私は私の推測では、の線に沿って何かになり、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を変更することができる場合は、最初のアプローチには問題はありません。

0

拡張メソッドの出現により、副作用をもたらすメソッドを扱うのが少し簡単になりました。たとえば、あなたの例では、それは

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

を言うと、何かがリストに起こっていること、それが明確になり

mylist.AddBar(); 

でそれを呼び出すために、はるかに直感的になります。

コメントに記載されているように、これはリストの変更がより混乱する傾向がありますので、リストで最も役立ちます。単純なオブジェクトでは、オブジェクトを適切に修正する傾向があります。

+0

これは実際の質問に答えるようです。つまり、Fooメソッドが渡されたパラメータを変更していることを一目瞭然にしないという点で最初のスタイルに問題があります。しかし、クラスを作成するというアイデアは、私がリストに追加/変更したいかもしれないすべての価値は狂っています。 – Mike

+0

私は一般的なアクセスとは対照的に、特にリストの観点から考えていました。私のジュニア開発者は、リストからの副作用が通常のオブジェクトよりも頻繁にスローされることがわかります。 これは、読み取り専用のプロパティとメソッドを使用するという考えがあります。 –

0

実際には、パラメータとしてリストを受け取るメソッドがリストを変更するということは予期せぬことではありません。あなたはそれだけでも、リストを変更する方法を禁止するものではありません。このようなインターフェイスを使用することにより

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パラメータは必要ありません。

関連する問題