22
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[C#]プロパティのgetアクセサの穴をふさぐ、堅牢な公開

Posted at

クラスのプロパティを公開する際に、外部から変更されたくない場合にgetアクセサを用いると思いますが、
その公開している型が参照型であった場合、一見変更できないように見えて、バリバリ変更できてしまっている状態になっています。

sample.cs
//外部から変更不可
readonly string s;
public string S
{
    get
    {
        return s;
    }
}

//外部から変更可能
readonly List<string> str;
public List<string> Str
{
    get
    {
        return str;
    }
}

このStrに対して、外部から要素を追加削除変更し放題になっています。
そこで、登場するのが、ReadOnlyCollection、ReadOnlyDictionaryなどの読み取り専用クラスになります。
使い方は簡単、これらのインスタンスを生成する際に、引数に読み取り専用としたいコレクションを指定するだけ。

sample.cs
readonly List<string> str = new List<string>();
public ReadOnlyCollection<string> Str
{
    get
    {
        return new ReadOnlyCollection<string>(str);
    }
}

readonly Dictionary<string, string> dict = new Dictionary<string, string>();
public ReadOnlyDictionary<string, string> Dict
{
    get
    {
        return new ReadOnlyDictionary<string, string>(dict);
    }
}

ちなみに、List strの変更は、ReadOnlyCollection Strにも反映されます。
つまるところ、ReadOnlyCollection StrはただのList strの(List strの参照を保持している)ラッパークラスということですね。

ただし、コレクションの要素に参照型が入っていれば同じことになるので、気をつけましょう。

sample.cs
//Tが参照型の時、コレクション自体は変更できないが、
//要素のインスタンス(Tクラス)内部を変更可能
readonly List<T> str = new List<T>();
public ReadOnlyCollection<T> Str
{
    get
    {
        return new ReadOnlyCollection<T>(str);
    }
}

これで、スティーブジョブズ級のコントロールが、容易に実現できるかも!?

22
16
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?