はじめに
参考:https://neue.cc/2011/12/13_358.html
.NET Framework 時代は ↓ で void
のインスタンスを得られますが、.NET9 ではエラーになるようです。
using System.Runtime.Serialization;
var v = FormatterServices.GetUninitializedObject(typeof(void));// エラー!
Assert.Equal(typeof(void), v.GetType());
FormatterServices
は古いクラスにマークされていたり .NET Framework -> .NET の流れで変更があったのでしょうか。コンパイルはエラーにならず、実行時エラーになるためランタイム側であれこれした結果かもしれません。
やはり void
インスタンスを取得できるのはまずかったか・・・
サンプルコード
テストコード
using Xunit;
public class __VoidInstanceTest
{
[Fact]
void CreateVoidError()
{
// 少なくとも .net9 では例外になる
Assert.Throws<ArgumentException>(() =>
System.Runtime.CompilerServices.RuntimeHelpers.GetUninitializedObject(typeof(void)));
}
[Fact]
void CreateRefStructError()
{
Assert.Throws<NotSupportedException>(() =>
System.Runtime.CompilerServices.RuntimeHelpers.GetUninitializedObject(typeof(Span<int>)));
}
[Fact]
void SkipConstructor()
{
var person = (Person?)System.Runtime.CompilerServices.RuntimeHelpers.GetUninitializedObject(typeof(Person));
Assert.NotNull(person);
Assert.Equal(null!, person.Name);
Assert.Equal(0, person.Age);
}
}
file class Person
{
internal string Name { get; } = "Default Name";
internal int Age { get; } = 20;
public Person() { }
public Person(string name, int age)
{
this.Name = name;
this.Age = age;
}
}
System.Runtime.CompilerServices.RuntimeHelpers
古いクラスマークされたクラスの置き換えクラスが用意されているようです。
そもそもの古いクラスはオブジェクトのシリアル化関係の用途のようです。GetUninitializedObject()
はコンストラクタを呼ばずにインスタンスを生成するという結構ハック的な処理をしています。
file class Person
{
internal string Name { get; } = "Default Name";
internal int Age { get; } = 20;
public Person() { }
public Person(string name, int age)
{
this.Name = name;
this.Age = age;
}
}
var person = (Person?)System.Runtime.CompilerServices.
RuntimeHelpers.GetUninitializedObject(typeof(Person));
Assert.NotNull(person);
Assert.Equal(null!, person.Name);
Assert.Equal(0, person.Age);
↑ の Person
クラスは引数ありと引数なしの2種類のコンストラクタがありますが、GetUninitializedObject()
によって得られたインスタンスはどちらのコンストラクタも経由していません。全てのフィールドが 0 または null
で埋められます。
おわりに
いろいろ試してみましたが、.NET9 で void
のインスタンスを取得する方法は見つけられませんでした。一方で面白いクラス(RuntimeHelpers
)を発見できたので、パフォーマンス関係に使えないか試してみようと思います。