public Foo()
{
EmptyResult result;
}
スタックに割り当てがあると思いますか、それとも効果的にノーオペレーションですか?
public Foo()
{
EmptyResult result;
}
スタックに割り当てがあると思いますか、それとも効果的にノーオペレーションですか?
C#コンパイラは、空の構造体に1バイトのサイズを強制します。だからクラス内またはスタック上のその構造体の任意のインスタンスは、1つのバイトを占有します
[StructLayout(LayoutKind.Sequential, Size=1)]
private struct EmptyResult
{
}
System.Byte
のインスタンスとまったく同じか:あなたは逆コンパイラで構造体を見ている場合は、これを見ることができますSystem.SByte
おそらくそれはそのアドレスを取ることができるようにそうする。 –
逆コンパイルする必要はありません。 'Marshal.SizeOf(typeof(EmptyResult))'を使うことができます。私はちょうどポストするつもりでしたが、遅すぎました。 –
@DavidHeffernan私はあなたが正しいと確信しています - それはあなたがそのアドレスを取ることができるだけでなく、2つのインスタンスが異なるアドレスを持つように。興味深いことに、Stroustrupは空のC++構造体について言及しています(http://www.stroustrup.com/bs_faq2.html#sizeofempte)。 –
フィールドがないAC#structのサイズは1です。この理由は、コンパイラが安全でないコードの&
演算子を使用して構造体のアドレスを取得できる必要があるためです。
あなたの構造体型は、byte
型とまったく同じ方法で処理されると思います。
あなたは、ILを勉強するidlasm.exe
を使用する場合は、あなたがEmpty
構造体のインスタンスを作成するラインで、あなたが表示されます:
.maxstack 1
.locals init ([0] valuetype Draft.Empty e)
をそしてEmpty
構造体の定義は次のとおりです。
.class private sequential ansi sealed beforefieldinit Draft.Empty
extends [mscorlib]System.ValueType
{
.pack 0
.size 1
} // end of class Draft.Empty
作成時に1バイトが割り当てられ、定義ではこのタイプのサイズは1です。
そうです。スタック上に1バイトを割り当てます。
注:リリースモードでコンパイルされたアセンブリから抽出されたEmpty
の定義。
JIT段階では、もちろんそれを最適化することができます –
@DavidHeffernan '新しいEmpty()。Equals(new Empty())'がどのようにtrueを返すか説明してください。スタックに実際のアドレスは必要ないのですか? (私は本当にJITワークフローに精通していません)。ありがとう –
'Equals()'は構造体の値の等価性をチェックします。フィールドがないので、 'EmptyResult'型のオペランドに対して' s1.Equals(s2) 'は常に' true'である場合があります。 –
コンパイラがこれを最適化することを願っています。 Fooにその行にブレークポイントを設定し、ヒットしたかどうかを確認します。 – Sayse
「int」型の変数を作成した場合、最適化されます。おそらくもっと良い例は、構造体を関数に渡すことです。 –