コンストラクタを回避してインスタンスを生成する(C#)
一時的にモックのようなものが欲しいことがありました。普通にnew(...)すればいいんですが、コンストラクタにたくさん引数があって準備が大変で嫌…みたいな感じです。
こういうときにRuntimeHelpers.GetUninitializedObject(Type)というのがあるみたいです。これを使うと、コンストラクタもフィールド初期化子も無視してインスタンスを生成できます。
interface IValue { int Value { get; } }
record Sample(int Value, string Name, DateTime Date) : IValue;
var sample = (Sample)RuntimeHelpers.GetUninitializedObject(typeof(Sample));
// sample.Date: DateTime.MinValue
if (sample is IValue v) { v.Value; }// 当然IValueとしても扱える
すごい。
昔はFormatterServices.GetUninitializedObjectが使われていたようですが、FormatterServicesはすでに古くなっています。
Formatter-based serialization is obsolete and should not be used. (https://learn.microsoft.com/ja-jp/dotnet/api/system.runtime.serialization.formatterservices)
このFormatterServices.GetUninitializedObjectですが昔はvoidのインスタンスも作れたみたいです。
neue cc - Voidインスタンスの作り方、或いはシリアライザとコンストラクタについて
ビックリですね。
現代の.NETではvoidのインスタンスは作れないようになっています。RuntimeHelpers.GetUninitializedObject(typeof(void))(FormatterServicesも同様)すると例外になります。
System.ArgumentException : Type is not supported.
他に作れないものとして代表的なのはstringなどがあるようです。以下のあたりを見てみるとなんとな~くダメそうなものがわかります。
可変長型やポインタ、ref構造体などもちゃんと?ダメなようです。