✨
Lookup型使ってみたら便利だったっていう話
なんの記事?
C#のLookup型を使ってみたら便利だったっていう話です!
Lookup型とは
Lookup型は、Dictionaryの要素の一つ一つがIEnumerableになっているデータ型です。
Dictionary< key , List<T> > 型を作りたくなったときには
ぜひ使用を検討してみてください。
ただし、インスタンスを作成した後キーや要素の追加、削除ができないのでご注意ください。
▼イメージ図▼
良いところ
- keyに対して複数のValueを持てる
- Linqから簡単につくれる
- 使い方がDictionaryとほぼ同じ
- 値やキーの追加削除が禁止されているのでセキュアに使える
- データ型の名前がわかりやすい
悪いところ
- 値やキーの追加削除が禁止されているので使い所を選ぶ必要がある
使い方
Listから作成します。作り方は簡単です。
*今回使用したのはILookup型です。Lookupとほぼ同じ機能を持っています。
//Listを作成したり受け取ったりする
List<Element> list = new List<Element>();
// 要素が持つNameプロパティをキーにしてILookupを作る
ILookup<string , Element> lookup = list.ToLookup(x => x.Name);
//使用側
//キーを指定するとIEnumerableが返ってくる
IEnumerable<Element> elements = lookup["key"];
//IEnumerableのためforeachで回して処理することができる
foreach(var element in elements)
{
Debug.Log(element.Value);
}
//要素側クラスの構成例
public class Element
{
public string Name { get; set; }
public int Value { get; set; }
}
※ 今回はILookup型を使いましたが、Lookup型へのキャストも可能です。
Lookup型はApplyResultSelectorという、
特定キー内の要素を加工して返すメソッドを持っているようです。
(未検証)
DIと組み合わせて使う
別記事で紹介した、
DIを使ってInterfaceのディクショナリーを作成する用法を
Lookup型に変更してみました。
この用途であれば、要素の不変性が利点になりますね!
public class ChangeImageLookup
{
readonly Lookup<string, IChangeImage> _lookup; //保管、索引のためのLookup
[Inject]
public ChangeImagePresenter( List<IChangeImage> list ) //複数のInterfaceをInjectで取得する
{
_lookup = (Lookup<string, IChangeImage>)list
.Distinct() //理屈上重複しないはずだけど一応重複削除
.ToLookup(x => x.Name); //NameをキーにしてLookupを作成
}
//索引できるようにGetterを書いておく
public IEnumerable<IChangeImage> Get(string name) => name == null ? null : _changeImageDictionary[name];
}
//使用側
IEnumerable<IChangeImage> changeImages = lookup["DefaultBack"];
Sprite image = //image の収得処理
//IEnumerableのためforeachで回して処理することができる
foreach(var changeImage in changeImages)
{
changeImage?.ChangeImage(image);
}
まとめ
Lookup型、便利でした!
要素の追加削除ができない、という点が利点になるようなケースはよくあるかと思います!
Dictonary<key,List<T>>などで宣言するよりも読みやすくなりますし、
型名から何をするクラスなのかわかりやすいのも、とても良いですね。
ぜひみなさんも利用検討してみてください!
謝辞
次のサイト様から素材をお借りました。
リファレンス
Lookup<TKey,TElement> クラス
ILookup<TKey,TElement> インターフェイス
Discussion