3

まず、KeyedCollectionを使用している理由を説明します。DLLを作成していて、コレクションに追加する必要のあるアイテムのリストがあり、配置した順序のままにしますが、インデックスとキーの両方でアクセスする必要もあります(キーはすでに定義したオブジェクトのプロパティ)。これを行うもっと簡単なコレクションが他にある場合は、私に知らせてください。

さて、DLLの内部でこのコレクションにアイテムを追加できる必要がありますが、追加したアイテムを削除/変更したくないため、DLLのエンドユーザーが読み取り専用として公開できるようにする必要があります。 。

私はこのサイト、他のサイト、グーグル一般を検索しましたが、ある種の読み取り専用のKeyedCollectionを取得する方法を見つけることができませんでした。私が最も近かったのはこのページ(http://www.koders.com/csharp/fid27249B31BFB645825BD9E0AFEA6A2CCDDAF5A382.aspx?s=keyedcollection#L28)でしたが、完全に機能させることができませんでした。

アップデート:

私はそれらのC5クラスを調べました。それは、他のコメントとともに、私自身の読み取り専用クラスを作成する方法をよりよく理解するのに役立ち、それは機能しているようです。ただし、通常のものを読み取り専用のものにキャストしようとすると問題が発生します。コンパイル時に変換できないというエラーが発生します。これが私が作成したコードです(最初の小さなクラスは私が最初に持っていたものです):

public class FieldCollection : KeyedCollection<string, Field>
{
    protected override string GetKeyForItem(Field field)
    {
        return field.Name;
    }
}

public class ReadOnlyFieldCollection : KeyedCollection<string, Field>
{
    protected override string GetKeyForItem(Field field)
    { return field.Name; }

    new public void Add(Field field)
    { throw new ReadOnlyCollectionException("This collection is read-only."); }

    new public void Clear()
    { throw new ReadOnlyCollectionException("This collection is read-only."); }

    new public void Insert(int index, Field field)
    { throw new ReadOnlyCollectionException("This collection is read-only."); }

    new public bool Remove(string key)
    { throw new ReadOnlyCollectionException("This collection is read-only."); }

    new public bool Remove(Field field)
    { throw new ReadOnlyCollectionException("This collection is read-only."); }

    new public bool RemoveAt(int index)
    { throw new ReadOnlyCollectionException("This collection is read-only."); }
}

この変数を定義している場合:

private FieldCollection _fields;

次に、これを行います。

public ReadOnlyFieldCollection Fields;
Fields = (ReadOnlyFieldCollection)_fields;

コンパイルに失敗します。どちらも同じクラスから継承しているので、「互換性がある」と思いました。コレクションを作成したばかりの読み取り専用タイプとしてキャスト(または公開)するにはどうすればよいですか?

4

4 に答える 4

2

組み込みのソリューションも知りません。これは、コメントに対して私が与えた提案の例です。

    public class LockedDictionary : Dictionary<string, string>
    {
        public override void Add(string key, string value)
        {
            //do nothing or log it somewhere
            //or simply change it to private
        }

        //and so on to Add* and Remove*

        public override string this[string i]
        {
            get
            {
                return base[i];
            }
            private set
            {
                //...
            }
        }
    }

KeyValuePair リストとその他すべてを反復処理できますが、書き込み操作には使用できません。必要に応じて必ず入力してください。


編集 ソートされたリストを作成するために、基本クラスを からDictionary<T,T>に変更できますHashtable

次のようになります。

    public class LockedKeyCollection : System.Collections.Hashtable
    {
        public override void Add(object key, object value)
        {
            //do nothing or throw exception?
        }

        //and so on to Add* and Remove*

        public override object this[object i]
        {
            get
            {
                return base[i];
            }
            set
            {
                //do nothing or throw exception?
            }
        }
    }

使用法:

        LockedKeyCollection aLockedList = new LockedKeyCollection();

        foreach (System.Collections.DictionaryEntry entry in aLockedList)
        {
            //entry.Key
            //entry.Value
        }

残念ながら、メソッドのアクセス修飾子を変更することはできませんが、オーバーライドして何もしないようにすることはできます。

于 2012-08-10T20:20:03.680 に答える
2

元の回答を修正するために編集しました。どうやら、今朝はカフェインが足りていないようです。

コレクションとディクショナリの読み取り専用ラッパーを提供する C5 コレクション ライブラリと、CLR チームが忘れていたその他のものを確認する必要があります。

http://www.itu.dk/research/c5/

また、 http: //www.nuget.org/packages/C5 で NuGet を介して C5 コレクション ライブラリを取得することもできます。

于 2012-08-13T17:09:06.377 に答える