MRが楽しい

MRやVRについて学習したことを書き残す

C#でリストやディクショナリのプロパティを読み取り専用で参照する

本日は C# の小ネタ枠です。
C#でリストやディクショナリのプロパティを読み取り専用で参照する方法について記事にします。

サンプルコード

・ExampleReadOnlyListData.cs

using System.Collections;
using System.Collections.Generic;

namespace ConstructorCheck
{
    public class ExampleReadOnlyListData
    {
        private List<string> p_TextList;
        public IReadOnlyList<string> TextList => p_TextList.AsReadOnly();

        public ExampleReadOnlyListData(string[] textList = null)
        {
            p_TextList = new List<string>(textList);
        }
    }
}

・使用例

ExampleReadOnlyListData readOnlyListData = new ExampleReadOnlyListData(new List<string> { "Alpha", "Beta" }.ToArray());
Console.WriteLine($"Test : {readOnlyListData.TextList.Aggregate((x, y) => x + ", " + y)}");

ReadOnlyクラス

以下のような読み取り専用のクラスが利用可能です。
これらのクラスにキャストすることでコレクション内の編集を制限できます。
docs.microsoft.com
docs.microsoft.com
docs.microsoft.com

AsReadOnly関数

List を対応する IReadOnlyList クラスに変換する関数です。
List を IReadOnlyList にキャストして公開するだけでは IReadOnlyList を List 型にキャストし戻して編集することができてしまいます。
docs.microsoft.com

AsReadOnly 関数で ReadOnly クラスを生成しておけば、再キャストした際に以下のエラーが発生するため、キャストしての編集も制限することができます。
・記述例

ExampleReadOnlyListData readOnlyListData = new ExampleReadOnlyListData(new List<string> { "Alpha", "Beta" }.ToArray());
List<string> listData = (List<string>)(readOnlyListData.TextList); // ここで以下のエラーが発生する

・発生エラー

InvalidCastException: Specified cast is not valid.

f:id:bluebirdofoz:20211217235849j:plain

ただし本関数は Dictionary では利用できません。
Dictionary の場合は今のところ、以下のようにキャストするしかありません。他に良い方法が見つかれば改めて更新します。
・ExampleReadOnlyDictionaryData.cs

using System.Collections;
using System.Collections.Generic;

namespace ConstructorCheck
{
    public class ExampleReadOnlyListData
    {
        private Dictionary<int, string> p_TextDictionary;
        public IReadOnlyDictionary<int, string> TextList => p_TextDictionary;
// ...