12

このコードを試してみたい:

public struct Direction
{
   private int _azimuth;

   public int Azimuth
   {
     get { return _azimuth; }
     set { _azimuth = value; }
   }       

   public Direction(int azimuth)
   { 
      Azimuth = azimuth
   } 
}

しかし、コンパイルに失敗します。構造体がすべてのフィールドを初期化する必要があることを理解しています。しかし、私はCLR\ILの内部で何が起こるかを理解しようとしています。他のmethod\property\thisなどの前にすべてのフィールドが必要な理由。

ありがとう。

4

6 に答える 6

11

値型はスタック上に作成されます (参照型内にネストされていない限り) スタック上のフィールド/場所について、CLR がそれらがゼロになることを保証できないことがあります (マネージド ヒープ上のフィールド/場所とは対照的に、ゼロに設定されることが保証されています)。したがって、それらは読み取られる前に書き込まれる必要があります。それ以外の場合は、セキュリティ ホールです。

構造体のデフォルト ctor (パラメーターをとらず、明示的に指定することはできません) は、構造体のすべてのフィールドをゼロに設定するため、実行後に構造体を使用できます。

new BimonthlyPairStruct()

ただし、パラメーター化された ctor を実装するときは、すべてのフィールドが初期化されていることを確認する必要があります。これは、CLR がコードを safe/Verified として渡すために必要です

関連項目: C# 第 2 版による CLR - Pg 188

于 2009-04-25T14:02:57.220 に答える
5

これは機能します:

  public Direction(int azimuth)
  {
    _azimuth = azimuth;
  }

仕様から:

Structコンストラクターはnew演算子で呼び出されますが、これはメモリが割り当てられていることを意味するものではありません。オブジェクトを動的に割り当ててそのオブジェクトへの参照を返す代わりに、構造体コンストラクターは単に構造体値自体(通常はスタック上の一時的な場所)を返し、この値は必要に応じてコピーされます。

基本的に、コンパイラーは、コンストラクターですべてのフィールドが初期化され、それらの値をコピーできることを確認する必要があり、関数またはプロパティの呼び出しを調べようとはしません。

于 2009-04-06T12:58:12.160 に答える
5

私はMSDNフォーラムで、デフォルトなしのコンストラクターを使用するとメモリのゼロ化がスキップされるため、このルールが適用されるという説明を見つけました。したがって、ランダムな値を含む一部のフィールドを回避するために、すべてのフィールドに初期化値を指定する必要があります。これは、パラメーターless defaultコンストラクターを呼び出すことで簡単に実現できますが、一部のフィールドを2回初期化する必要があります。

この説明が正しいかどうかはわかりませんが、合理的に聞こえます。

デフォルト以外の初期化子を定義する場合、C#ではメモリのゼロ化をスキップして初期化できるため、すべてのフィールドを設定する必要があります。そうしないと、初期化のパフォーマンスが2倍になります。(ごくわずかな)パフォーマンスへの影響を気にしない場合は、いつでも:this()初期化子への呼び出しを連鎖させてから、選択したフィールドのみを初期化できます。

于 2009-04-06T13:02:52.010 に答える
5

これは、構造体が System.Object ではなく System.ValueType から派生しているためです。System.ValueType は、オーバーライドできないデフォルト コンストラクターを実装しています。このデフォルト コンストラクターは、構造体のすべてのフィールドをデフォルト値で初期化します。したがって、クラスにパラメーター コンストラクターを実装する場合は、system.ValueType の既定の const を呼び出すように t0 も必要になります。なぜすべての値を初期化する必要があるのか​​ に答えるために、これは値がスタックメモリに格納されているためです。

于 2009-04-06T12:57:16.937 に答える
2
public struct Direction
{
    public int Azimuth { get; private set; }

    public Direction(int azimuth) : this()
    {
        Azimuth = azimuth;
    }
}
于 2009-04-06T12:42:54.023 に答える
-1

プロパティではなく、フィールドを初期化する必要があります。

于 2009-04-06T12:42:12.730 に答える