[解決済み】.NETで構造体のデフォルトコンストラクタを定義できないのはなぜですか?
質問
.NETでは、値型(C#の場合
struct
) は、パラメータを持たないコンストラクタを持つことができません。というのも
この記事
これはCLI仕様で義務付けられていることです。つまり、すべての値型に対してデフォルトのコンストラクタが作成され、すべてのメンバをゼロに初期化する(あるいは
null
).
なぜ、このようなデフォルトのコンストラクタを定義してはいけないのでしょうか?
些細な使い方としては、有理数に対するものがあります。
public struct Rational {
private long numerator;
private long denominator;
public Rational(long num, long denom)
{ /* Todo: Find GCD etc. */ }
public Rational(long num)
{
numerator = num;
denominator = 1;
}
public Rational() // This is not allowed
{
numerator = 0;
denominator = 1;
}
}
現在のバージョンの C# を使用した場合、デフォルトの Rational は
0/0
というのは、あまり格好のいいものではありません。
PS : C# 4.0ではデフォルトのパラメータで解決するのか、それともCLRで定義されたデフォルトのコンストラクタが呼び出されるのでしょうか?
ジョン・スキート が答えました。
あなたの例で言うと、誰かがやったときにどうなってほしいか。
Rational[] fractions = new Rational[1000];
コンストラクタを1000回走らせるべき?
もちろん、そうすべきです。だから、最初にデフォルトのコンストラクタを書いたのです。CLRは
デフォルトのゼロ処理
コンストラクタが明示的に定義されていない場合は、使用した分だけを支払うことになります。この場合、使用した分だけ支払うことになります。
Rational
を使用します(そして、1000のコンストラクションを最適化したい)。
List<Rational>
は配列ではなく
この理由は、デフォルトのコンストラクタを定義できないほど強いものではないと私は考えています。
解決するには?
<ストライク 注意 C# 6 では構造体にパラメータなしのコンストラクタを宣言できるようになる予定ですが、それでもすべての状況で呼び出されるわけではありません(例:配列の生成など)。 (最終的にこの機能 はC# 6では追加されませんでした。 ).
EDIT: Grauenwolf氏のCLRに関する見識により、以下の回答を編集しました。
CLRでは、値型にパラメータなしのコンストラクタを持たせることができますが、C#ではできません。これは、コンストラクタが呼び出されないのに呼び出されるという期待を持たせてしまうからだと思います。例えば、こんなことを考えてみてください。
MyStruct[] foo = new MyStruct[1000];
CLRは、適切なメモリを割り当て、それをすべてゼロにするだけで、これを非常に効率的に行うことができます。もし、MyStructコンストラクタを1000回実行しなければならないとしたら、それはかなり効率が悪いでしょう。(実際には、それはありません - もしあなたが する パラメータレスコンストラクタがあれば、配列の生成時やインスタンス変数の初期化時に実行されることはありません)。
C#の基本ルールは、"あらゆる型のデフォルト値は、いかなる初期化にも依存してはならない"です。現在、彼らは ができた。 パラメータレスコンストラクタを定義することは許されても、そのコンストラクタをすべてのケースで実行することは要求されません。(少なくとも、そのような議論になると思います)。
編集部:あなたの例で言うと、誰かがそうしたらどうしたいですか?
Rational[] fractions = new Rational[1000];
コンストラクタを1000回走らせるべき?
- そうでなければ、1000個の無効な有理数で終わってしまう
- もしそうだとすると、これから配列に本当の値を埋めようとするときに、無駄な作業をする可能性があります。
EDIT: (もう少し質問に答えると)パラメータレスコンストラクタはコンパイラが作っているわけではありません。CLRに関する限り、値型はコンストラクタを持つ必要がありません。
できる
ILで書くと と書くと、"
new Guid()
C# では、通常のコンストラクタを呼び出したときとは異なる IL が出力されます。以下はその例です。
このSOの質問
は、その点についてはもう少し詳しく説明します。
I 容疑者 フレームワークには、パラメータレスコンストラクタを持つ値型がないのです。NDepend にうまく頼めば教えてくれるに違いないのですが・・・。C# がそれを禁止しているという事実は、それがおそらく悪い考えであると考えるのに十分な大きなヒントです。
関連
-
[解決済み】エラー。「戻り値を変更できません」 C#
-
[解決済み】文字列が有効な DateTime " format dd/MM/yyyy " として認識されなかった。
-
[解決済み】なぜこのコードはInvalidOperationExceptionを投げるのですか?
-
[解決済み】C#のequal to演算子でtextとvarcharのデータ型は互換性がない
-
[解決済み] .NET String.Format()で数値の千の位にカンマを追加する
-
[解決済み] .NETにおけるstructとclassの違いは何ですか?
-
[解決済み] 構造体のsizeofは、なぜ各メンバーのsizeofの合計と等しくないのですか?
-
[解決済み] なぜクラスではなくストラクチャーを選ぶのか?
-
[解決済み] なぜC言語では構造体を頻繁にtypedefする必要があるのですか?
-
[解決済み】なぜ.NETはデフォルトで銀行員の丸めを使用するのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】GDI+、JPEG画像をMemoryStreamに変換する際にジェネリックエラーが発生しました。
-
[解決済み】コンパイルエラー「未割り当てのローカル変数を使用しています」が発生したのはなぜですか?
-
[解決済み] メンバー '<メンバー名>' にインスタンス参照でアクセスできない
-
[解決済み] 'IEnumerable<SelectListItem>' 型の ViewData アイテムで、キーが国であるものは存在しない。
-
[解決済み】ランダムなブーリアンを生成する最速の方法
-
[解決済み】インデックスが範囲外でした。コレクションパラメータname:indexのサイズより小さく、非負でなければなりません。
-
VSでscanfエラーを恒久的に解決するには、ソースファイルを作成し、自動的に#define _CRT_SECURE_NO_WARNINGS 1を追加してください。
-
[解決済み】スレッド終了またはアプリケーションの要求により、I/O操作が中断されました。
-
[解決済み] .NETにおけるstructとclassの違いは何ですか?
-
[解決済み】構造体の "new "は、ヒープやスタックに割り当てるのですか?