2009-09-15 5 views
7

このトピックに関連するすべての質問を読んで、structのデフォルトのコンストラクタがC#で利用できない理由を説明しますが、この状況に直面したときに一般的な行動方針を提案した人はいません。デフォルトのコンストラクタを隠すために、盲目的に構造体をクラスに変換していますか?

明白な解決策は、structclassに変換し、その結果を処理することです。

他にもstructとして保存するオプションはありますか?

この状況に私たちの内部コマースAPIオブジェクトの1つを使用しました。デザイナーはそれをclassからstructに変換しました。そして、以前のプライベートであったデフォルトのコンストラクタは、オブジェクトを無効な状態にしています。

オブジェクトをstructのままにしておくと、状態の有効性をチェックするメカニズムが導入されるはずです(のようなもの)。私は多くの抵抗があり、「誰でもAPIを使うべきだ」という説明は、デフォルトコンストラクタを使うべきではありません。 (注:問題のオブジェクトは、staticファクトリメソッドを介して「適切に」構築され、他のすべてのコンストラクタはinternalです。)

は、誰もが簡単に一も二もなく、このような状況でclass ESにそのstruct秒に変換されていますか?

編集:私はstructように、オブジェクトのこのタイプを維持する方法についていくつかの提案を見たい - 上記の問題のオブジェクトは、多くの方が適しstructとしてclassとしてよりもあります。

+0

これは大きな質問です。ゼロアウト状態が有効になるように構造体を設計することはできますが、それだけでは必ずしも使用可能なAPIが得られるわけではありません。デフォルトのコンストラクターがある場合は、IDEにポップアップして最小の抵抗のパスを提供するため、必然的に呼び出す人もいます。コンパイラがキャッチしなければならない問題につながるか、不変のゼロアウト構造体にプロパティを設定しようとして時間を浪費します。私はC#でデフォルトのコンストラクタを隠すことができて、実際にゼロスアウトされた構造体が本当に必要な場合は、デフォルト(...)を呼び出すようにしてください。 –

+0

実際にこれ以上調べてみると、使いやすさの問題は実際にはコンパイラではなくIntellisenseにあると思います。かつて、Visual StudioはIntellisenseのデフォルトのコンストラクタを表示していなかったようです。私の意見では、これは賢明なことです。しかし、人々は(ここを参照してください)(http://stackoverflow.com/questions/1429495/blindly-converting-structs-to-classes-to-hide-the-default-constructor)、ある時点で変更されている必要がありますが、 Visual Studio 2010は最初のオプションとして空のコンストラクタをポップアップしているので、 –

答えて

4

structの場合、デフォルトの構成インスタンス(フィールドがすべてゼロ)が有効な状態になるようにタイプを設計します。いいえ、classの代わりに[]をstructの代わりに任意に使用しないでください。不変の参照型を使用すると何も問題ありません。

私の提案:

  • structを使用する理由が有効であることを確認してください([リアル]プロファイラは、非常に軽量なオブジェクトの重い配分から生じた大幅なパフォーマンスの問題を明らかにしました)。
  • デフォルトで構築されたインスタンスが有効になるようにタイプを設計します。
  • 型のデザインがネイティブ/ COM相互運用機能の制約によって決まる場合は、機能をラップし、structをラッパー(プライベートネストされた型)の外部に公開しないでください。そのようにして、制約付きタイプ要件の適切な使用を簡単に文書化して検証できます。
+0

良い答え。オブジェクトが参照型である場合に問題がより簡単に導入されるため、あなたが言ったことのどれも適用されません。なぜそれが構造体に変換されたのですか?しかし、他の多くのケースでは、不変の参照型を使用することは実行可能な解決策になります。 –

1

理由は、構造体(System.ValueTypeのインスタンス)がCLRによって特別に扱われるためです。すべてのフィールドが0(またはデフォルト)で初期化されているためです。実際には作成する必要はありません。宣言するだけです。これがデフォルトコンストラクタが必要な理由です。

次の2つの方法でこれを回避することができます

  1. あなたが示していると.NET 2.0で
  2. がNULL可能<T>を使用することを検討して同じように、それが有効な構造体であるかどうかを示すためには、IsValidのようなプロパティを作成します。初期化されていない(ヌル)構造体を許可します。非ので、微妙ですが、ハード初期化されていないため、デバッグNullReferenceExceptionsへ
(マルチスレッド環境でより出てくるのメモリ使用量とオブジェクトの同一性の観点で)いくつかの非常に微妙な影響を持つことができるクラスに構造体を変更する

、およびオブジェクト。

0

次の式で示されているデフォルトコンストラクタを定義する可能性はない理由:デフォルトのコンストラクタ千呼び出しここ

  1. 3つのオプションを持っている

    new MyStruct[1000]; 
    

    は、または

  2. 構造体には参照が含まれている可能性があることに注意してください。参照を初期化または空白化しないと、任意のメモにアクセスする可能性がありますry)、または
  3. 割り当てられたメモリをゼロ(バイトレベル)で空白にします。

.NETは構造体とクラスの両方で同じことを行います。フィールドと配列要素はゼロでブランクアウトされます。これはまた、構造体とクラスの間のより一貫した動作をもたらし、安全でないコードも発生しません。また、.NETフレームワークがnew byte[1000]のようなものを特化しないようにすることもできます。

これはstruct .NETのデフォルトのコンストラクタです。それはすべてのバイトをゼロにします。

  • NullableHasValueのような)構造体にAM-I-初期化プロパティを追加します。

    は今、これを処理するためには、オプションのカップルが持っています。

  • ゼロ設定された構造体を有効な値にすることができます(0は10進数の有効な値です)。
関連する問題