1

読み取り専用にしたいコレクションプロパティを持つインターフェイスを作成しています。インターフェイスのユーザーがコレクションを変更できるようにしたくありません。読み取り専用コレクションプロパティを作成するために私が見つけた典型的な提案は、プロパティのタイプを次のようにIEnumerableに設定することです。

private List<string> _mylist;
public IEnumerable<string> MyList
{
get
    {
        return this._mylist;
    }
}

ただし、これは、ユーザーがIEnumerableをリストにキャストして変更することを妨げるものではありません。

Yield直接返す代わりにキーワードを使用する_mylistと、インターフェイスのユーザーがコレクションを変更できなくなります。実際のコレクションではなく、オブジェクトを1つずつ返すだけなので、そう思います。

 private List<string> _mylist;
public IEnumerable<string> MyList
{
get
    {
        foreach(string str in this._mylist)
        {
            yield return str;
        }
    }
}
4

5 に答える 5

5

これは、クラスのユーザーがリストにキャストバックしてメンバーにアクセスするのを防ぐための合理的な方法です。もう1つのオプションは、_mylistを使用することです。AsReadOnly() 。これは。を返しますReadOnlyCollection<T>

ただし、ユーザーが他の内部型にキャストすることでAPIを「破壊」する方法について心配する必要はありません。のパブリックAPIを配置した場合IEnumerable<T>、これはエンドユーザーが使用する(または使用する必要がある)ものであり、にキャストしようとはしませんList<T>。ユーザーが不適切なことをしたり、このようにAPIを壊したりするのを防ぐことは、特にすべての不適切な使用を防ぐことができないため、せいぜい問題があります。

于 2010-05-03T23:28:13.277 に答える
4

はい、不変です。

ただし、ReadOnlyCollection<string>代わりに使用する必要があります。

例えば:

MyClassName() {  //(Constructor)
    MyList = new ReadOnlyCollection<string>(_myList);
}

private List<string> _mylist;
public ReadOnlyCollection<string> MyList { get; private set; }
于 2010-05-03T23:26:38.357 に答える
3

はい、それは機能します。しかし、それが唯一の方法ではありません。.NET3.5で機能する別の方法は次のとおりです。

public IEnumerable<string> MyList
{
    get { return _myList.Skip(0); }
}

あなたがそれをすることができる他のいくつかの方法も示しているこの質問から取られました。

( Googleを使用して見つかりました)。

于 2010-05-03T23:27:39.500 に答える
1

クラスを使用するコードが完全に信頼できる場合は、とにかく常にプライベートフィールドを反映してアクセスできます。かなり失礼ですが、戻り値をキャストする方がわずかに優れています。ユーザーがあなたの財産をキャストして状態を破壊した場合、それはユーザー自身の責任です。

リストインスタンスをIEnumerableとして直接返すことの利点の1つは、LINQがIEnumerableの基本的なコントラクトに違反することなく(列挙によっても実行できるため)、ElementAt()やCount()などのメソッドへのアクセスを最適化できることです。

于 2010-05-04T01:14:03.567 に答える
0

はい、結果のシーケンスは読み取り専用になります。また、実行が延期されるという利点もあるため、一部のクライアントコードがシーケンス内のアイテムを列挙するまで、ループは実際には評価されません(ただし、クライアントコードが列挙しようとする前に内部コレクションが変更された場合、予期しない結果が生じる可能性があります)。 。

于 2010-05-03T23:25:37.750 に答える