• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:C#でプロパティをもつ構造体型の変数を使う)

C#でプロパティをもつ構造体型の変数を使う

このQ&Aのポイント
  • C#のプログラムで、プロパティを持つ構造体型の変数を使う際、文法エラーが発生する場合があります。
  • 特に、構造体の定義を変更し、プロパティにセッターとゲッターを追加すると、変数の使用に関するエラーが発生することがあります。
  • また、構造体の配列に値を割り当てずに要素にアクセスする場合、エラーは発生しません。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.3

どうも、この質問が気になって、ちょっと調べてみたのですが、参考URLの中の、 >各フィールドは未割り当てのままになり、すべてのフィールドが初期化されるまではオブジェクトを使用できません。 というのと、 >構造体は new 演算子を使用せずにインスタンス化できます。このような場合、コンストラクタの呼び出しが行われないため、 を考え合わせると、z.aを明示的に初期化しない為にエラーが出ているのではないでしょうか?(エラーのメッセージに不満は残りますが) 試しに、aをpublicにして、 S z; z.a=0; とすると、エラーは出ません。 new演算子を使用すると、適切なコンストラクタが呼び出される、と書かれており、それによって、メンバは初期化されるようです。逆に言うと、privateなメンバを持つ構造体は、明示的なパラメータを持つコンストラクタを定義して初期化するか、new演算子に頼るかしないと、使えない、ということになりますね。 ちなみに、構造体は宣言だけで実体は作られます。値型ですから。

参考URL:
http://msdn.microsoft.com/ja-jp/library/0taef578%28v=VS.90%29.aspx
akayoroshi
質問者

お礼

 ありがとうございます。 プロパティを使ったことではなく、フィールドをprivateにしたことによるエラーだったと行くことですか。 > privateなメンバを持つ構造体は、明示的なパラメータを持つコンストラクタを定義して初期化するか、new演算子に頼るかしない  納得しました。  配列の場合は、配列要素についても適切なコンストラクタが呼び出されるということのようですね。

その他の回答 (2)

  • seastar3
  • ベストアンサー率69% (99/142)
回答No.2

C言語とは違い、原則として、C#はポインタを扱えない仕様にしています。したがって構造体でも宣言だけでメモリーを確保するものではなく、実体化が必要なオブジェクト扱いになります。メソッドが加われば、間違いなくクラス扱いですから、逆に先のやり方ができる方が不自然な気がしました。 結果オーライでいい加減ですが、new を使って実体化するように統一してコーディングしていけば、エラーは防げることでしょう。

akayoroshi
質問者

お礼

もともとのプログラムに近づけると struct S : System.IComparable<S> { public int A, B; public int CompareTo(S z) { int compare=A.CompareTo(z.A); return (compare != 0) ? compare : B.CompareTo(z.B); } } class Program { static void Main(string[] args) { S x, y; x.A = 1; x.B = 2; y.A = 3; y.B = 4; Console.WriteLine(x.CompareTo(y)); } } で、構造体Sにはpublicなメソッドがありました。このフィールドAとBにアクセス制限をかけようとしてプロパーティに変更したところ、質問のような状況に陥ったというわけです。

  • seastar3
  • ベストアンサー率69% (99/142)
回答No.1

 解説を確認していないので、推測が多いので参考にならないかもしれませんが、ちょっと説明してみます。  最初のコードは構造体にセッタメソッドもゲッタメソッドもないので、純粋に構造体で、配列と同様にいきなり使えるのでしょう。  それに対して後のコードはセッタとゲッタを持つ構造体で、オブジェクトクラス扱いで準備されるのでしょう。したがっていったん名前を付けて実体化する手順を経なければ、後のSオブジェクトは抽象的オブジェクトのまま操作できないのでしょう。

akayoroshi
質問者

お礼

ご回答くださり、ありがとうございます。 構造体オブジェクトは値型なので、メモリを確保しただけで使えるものと理解していました。 Sが構造体型のとき、 S z = new S(); は、オブジェクトの実体を作るという意味ではなく、オブジェクトを作って、それを変数zにコピーすることによって変数のメモリ領域を初期化するということではありませんか。 変数の宣言 S z; と配列の確保(質問中の記載は誤っていました) S[] x = new S[10]; を較べたとき、前者で初期化がおこなわれないのであれば、後者は10個の配列要素の記憶場所を確保しているけれども、それぞれの配列要素は初期化がなされていないことになり、配列要素を参照してもエラーにならないのが腑に落ちなかったわけです。

関連するQ&A