私はそれが構造体のアンマネージ表現に影響documentation for [FieldOffset]によるC位.NETのユニオンフィールド - 実際にマネージコードで作業できますか?
[StructLayout(LayoutKind.Explicit)]
public struct MyUnion
{
[FieldOffset(0)]
public string MyString;
[FieldOffset(0)]
public Version MyVersion;
}
このような構造体を定義しました。しかし私の驚いたことに、マネージコードでもうまくいくように思えます。dotTraceでメモリ使用量をプロファイルすると、各MyUnion
インスタンスは1つのポインタ(x64の8バイト)のサイズです!値はまだ完全に安全であるようです。
var stringInside = new MyUnion { MyString = "The string" };
var versionInside = new MyUnion { MyVersion = new Version(1, 2, 3, 4) };
Console.WriteLine(stringInside.MyString); // The string
Console.WriteLine(versionInside.MyVersion); // 1.2.3.4
間違ったフィールドにアクセスするとどうなりますか?
var whatIsThis = stringInside.MyVersion;
var andThis = versionInside.MyString;
Console.WriteLine("{0} (type = {1})", whatIsThis, whatIsThis.GetType().FullName); // The string (type = System.String)
Console.WriteLine("{0} (type = {1})", andThis, andThis.GetType().FullName); // 1.2.3.4 (type = System.Version)
まだこの例えば、含まれるオブジェクトの実際の型が保存されているという意味で「作品」が、もちろん何のコンパイラが考え、どのようなランタイムは思っ間の切断が今そこにあります
Console.WriteLine("Compiler: is it a string? {0}", versionInside.MyString is string); // True
Console.WriteLine("Runtime: is it a version? {0}", versionInside.MyString.GetType() == typeof(Version)); // True
このような組合を使用することはどのくらい危険ですか?私はここに見られる行動に頼ることができますか?それは他の方法で壊れる可能性はありますか?特に、このようなコードを使用するのは安全ですか?
if (versionInside.MyString.GetType() == typeof(string))
{
Console.WriteLine("OK, it's a string, use the MyString field");
}
else
{
Console.WriteLine("OK, it's a Version, use the MyVersion field");
}
従来、組合の目的は記憶を節約することです。これは実際問題ですか?今日の複雑さ/難読化に値するでしょうか? –
はい、もちろんです。十分なデータがある場合、メモリは常に問題になります。 – EM0
それをうまく文書化してください - あなたはこれを驚かせていくつかの開発者を捕まえます(とにかく50歳未満の人)。 –