2011-01-20 9 views
47

List<T>を読み取り専用に公開することができますが、私的に設定することはできますか?これは動作しませんリスト<T>プライベートセットで読み取り専用

public List<string> myList {readonly get; private set; } 

あなたが行う場合でも:

public List<string> myList {get; private set; } 

あなたはまだこれを行うことができます。

myList.Add("TEST"); //This should not be allowed 

私はあなたが持っている可能性が推測:

public List<string> myList {get{ return otherList;}} 
private List<string> otherList {get;set;} 

答えて

87

あなたはコンセプトを混ぜていると思います。

public List<string> myList {get; private set;} 

すでに "読み取り専用"です。あなたは「私は人々がリストに内容を変更できるようにしたくない」のような読み取り専用リストが必要な場合には、このクラスの外には、何も、しかしList<string>

の別のインスタンスにmyListを設定することはできませんされ、 ReadOnlyCollection<string>を公開する必要があります。最初のコードスニペットでは、他の人がリストを操作することができますが、あなたが持っているもののリストに変更することはできませんことを

private List<string> actualList = new List<string>(); 
public ReadOnlyCollection<string> myList 
{ 
    get{ return actualList.AsReadOnly();} 
} 

注:あなたは経由でこれを行うことができます。 2番目のスニペットでは、他のスニペットでは変更できない読み取り専用のリストを取得します。

+2

大きなポイントに不要なキャストを防ぎたい場合。多くの人々が参照型の概念を欠いており、参照を読み取り専用に設定しています。 +1 –

+4

IList としてReadOnlyCollectionを使用する方がよいでしょう。 – Joe

+0

+1。 System.Collections.ObjectModel.ReadOnlyCollectionをパブリックに戻すことは、パブリックプロパティで「プライベートセット」を使用するよりも優れています。これは、コンパイル時チェックを行うためです。つまり、読み取り専用のコレクションでAdd()またはRemoveAt()を使用するとコンパイルエラーが発生しますが、「プライベートセット」は無効になります。 – MikeTeeVee

11

あなたが読み取り専用コレクション使用ReadOnlyCollection<T>、ないList<T>たい場合:

public ReadOnlyCollection<string> MyList { get; private set; } 
4

ReadOnlyCollection<T>と呼ばれるコレクションがあります - あなたが探しているものということでしょうか?

4

ListのAsReadOnly()メソッドを使用して、読み取り専用のラッパーを返すことができます。

1

なぜあなたはリストを使用していますか?あなたが本当に公開することは今のクラスのユーザーがリストをchagngeアイテムを読み取ることはできませんが

public IEnumerable<string> myList { get; private set; } 

のIEnumerableであるように聞こえます。

+1

に欠陥があります。List <>としてキャストして値を追加できます。MyClass m = new MyClass(); 一覧リストとして X = m.Values。 x.Add( "test"); foreachの(m.Valuesに、文字列s) {Console.WriteLineを(S)。 } –

+4

はい、あなたは**できます**多くのことをします。もちろん、リスト以外のものにmyListを設定することもできます。この場合、そのコードは壊れます。私は通常、カプセル化を意図的に無視している人々によって引き起こされる問題については心配しません。 – tster

+1

「カプセル化を無視する」人々を心配する必要はありません。カプセル化はカプセル化であり、あるタイプを別のタイプにキャストすることはカプセル化とは関係ありません。もしあなたがそれをやろうとしたら、それは正しいことです。 –

1

あなたはまた、あなたの通常のリストを作成しますが、IEnumerableを型のプロパティを通してそれを公開することができ

private List<int> _list = new List<int>(); 

public IEnumerable<int> publicCollection{ 
    get { return _list; } 
} 
+0

に欠陥があります。 List <>としてキャストして値を追加できます。MyClass m = new MyClass();リスト x = m。リストとしての値; x.Add( "test"); foreach(m.Valuesの文字列){Console.WriteLine(s);} } –

+1

確かに_list.AsEnumerable()もListにキャスト可能ですが、私の驚きです。 'リスト'に 'IEnumerableを'を唱えることができることへの依存を取っ –

+0

誰もが愚かなことだします。 –

4
private List<string> my_list; 

public ReadOnlyCollection<string> myList 
{ 
    get { return my_list.AsReadOnly(); } 
    private set { my_list = value; } 
} 
10

<>

private List<string> myList; 

public IList<string> MyList 
{ 
    get{return myList.AsReadOnly();} 
} 
3
private List<string> _items = new List<string>();   

    public ReadOnlyCollection<string> Items 

    { 

     get { return _items.AsReadOnly(); } 

     private set { _items = value } 

    } 
2
private List<string> myList; 

public string this[int i] 
{ 
    get { return myList[i]; } 
    set { myList[i] = value; } 
} 
のIListを実装戻るReadOnlyCollection、
11

IEnumerablを使用することをお勧めします電子

private readonly List<string> _list = new List<string>(); 

public IEnumerable<string> Values // Adding is not allowed - only iteration 
{ 
    get { return _list; } 
} 
+10

これは欠陥があることを除いては良いアプローチです:MyClass m = new MyClass();リスト x = m。リストとしての値; x.Add( "test"); foreach(m.Valuesの文字列){Console.WriteLine(s);} } //これにより、キャストだけで値を追加できます。 –

+5

さて、これはハックです:)リフレクションを使って要素を内部コレクションに追加することもできます。 IEnumerableは、MyClassクライアントから実装を隠します。 LinkedListを使用していないことを確認しますか? –

+3

あなたはいつでもコレクションタイプを見つけることができますので、私はいつも確実です。もしあなたがそれをやろうとしたら、それは正しいことです。誰もがアイテムを追加するためにオブジェクトを「ハックする」ためにリフレクションを使用できますが、それについてはあまりできません。適切な技術を実践し、フレームワークを実用的に使用することはすべてあなたができることです。 –

3

ここでは少し遅れ片道

public class MyClass 
    { 
     private List<string> _myList; 
     public ReadOnlyCollection<string> PublicReadOnlyList { get { return _myList.AsReadOnly(); } } 

     public MyClass() 
     { 
      _myList = new List<string>(); 
      _myList.Add("tesT"); 
      _myList.Add("tesT1"); 
      _myList.Add("tesT2"); 

      //(_myList.AsReadOnly() as List<string>).Add("test 5"); 
     } 

    } 
+1

Mmm ...あなたはPublicReadOnlyListをgetter new ReadOnlyCollectionで使うことができると思います。(_myList) –

0

ですが、それにもかかわらず:それはまだコレクションを修正するためのすべてのメソッドを公開するので、私はReadOnlyCollectionラッパーを使用して好きではない、これはすべてのスロー実行時にアクセスされるときはNotSupportedExceptionです。つまり、IListインターフェイスを実装していますが、実行時に同じ契約に違反します。

は、私が本当に不変のリストを露出していますことを表現するために、私は通常の長さと( this CodeProject articleで説明) IEnumerableにインデクサを追加するカスタム IIndexableインタフェースに頼ります。それは最初の場所IMHOで行われていたはずのラッパーです。

-1

私は、このオプションはまだ言及見ていない:

private List<string> myList; 

public List<string> MyList 
{ 
    get { return myList.AsReadOnly().ToList(); } 
} 

これは読み取り専用のリストを公開できるようにする必要があります。

+0

これは良くありません。まず、リストをラップするために 'ReadOnlyCollection 'を作成しています。 'ReadOnlyCollection 'のインスタンスは、変更可能な 'IList 'インタフェースを実装し、実行時に変更されるとスローします。しかし、あなたはそのコレクションを全ての内容を新しい 'List 'にコピーした後にそのコレクションを破棄します。元のリストではありませんが、修正が可能です。また、このコードは、不変であることが意図されているが実際には誤って変更可能なコピーである可変メンバーを公開するため、誤解を招く。 –

3

.NET 4.5フレームワークでは、IReadOnlyListインターフェイスのみを公開できます。 のような何か:

private List<string> _mylist; 
public IReadOnlyList<string> myList { get {return _myList;} } 

またはあなたがIListの

private List<string> _mylist; 
public IReadOnlyList<string> myList { get {return new List<string>(_myList);} } 
関連する問題