IEnumerableの実装に挑戦してみたいと思います。
こちらのクラスはOnlyOneCollectionとコレクションを銘打ってはいますが、実際は要素数が0または1つのみ格納できるコンテナクラスとなっております。使い道としてはNull許容の変数をの代わりに、nullの場合要素数が0のOnlyOneCollection>T<.None()を生成し、要素がある場合OnlyOneCollection>T<.One(T value);を生成ます。内部の要素は基本的にforeachか、ToList()で変換してLINQで取り出して使うことになります。そうすることでnullチェックを省くことが出来ます。
ソースコード
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection.Metadata.Ecma335;
using System.Runtime.InteropServices;
using System.Linq;
public class OnlyOneCollection<T> : IEnumerable<T>
{
T? _value;
OnlyOneCollection()
{
}
OnlyOneCollection(T value)
{
_value = value;
}
public static OnlyOneCollection<T> One(T value)
{
return new OnlyOneCollection<T>(value);
}
public static OnlyOneCollection<T> None()
{
return new OnlyOneCollection<T>();
}
public T Value
{
set
{
_value = value;
}
}
public IEnumerator<T> GetEnumerator()
{
if (_value is not null)
{
yield return _value;
}
else
{
yield break;
}
}
IEnumerator IEnumerable.GetEnumerator() => (IEnumerator) GetEnumerator();
public void Clear()
{
_value = default;
}
public List<T> ToList()
{
if (_value is not null)
{
return new List<T> { _value };
}
else
{
return new List<T>();
}
}
}
public class Program
{
public static void Main()
{
var vars = OnlyOneCollection<string>.None();
foreach(var v in vars)
{
// 実行されない
Console.WriteLine(v);
}
vars = OnlyOneCollection<string>.One("A");
foreach(var v in vars)
{
// 実行される
Console.WriteLine(v);
// 結果
// A
}
vars.Value = "B";
vars.ToList().ForEach(e =>
{
// 実行される
Console.WriteLine(e);
// 結果
// B
});
vars.Clear();
foreach(var v in vars)
{
// 実行されない
Console.WriteLine(v);
}
}
}
思い付きで作成しましたが、foreachが出来ましたので、IEnumerable<T>の実装として動いているようです。
コメント