web-dev-qa-db-ja.com

constパラメータがC#で許可されないのはなぜですか?

特にC++開発者にとっては奇妙に見えます。 C++では、メソッド内で状態が変更されないように、パラメーターをconstとしてマークしていました。 refで渡すためにconst refを渡し、状態が変更されないことを確認するなど、他のC++固有の理由もあります。しかし、なぜC#のメソッドパラメーターconstとしてマークできないのですか?

次のようにメソッドを宣言できないのはなぜですか?

    ....
    static void TestMethod1(const MyClass val)
    {}
    ....
    static void TestMethod2(const int val)
    {}
    ....
97
Incognito

他の良い答えに加えて、CスタイルのconstnessをC#に入れないもう1つの理由を追加します。あなたが言った:

メソッドで状態が変更されないようにするために、パラメーターをconstとしてマークします。

Constが実際にそれを行った場合、それは素晴らしいことです。 Constはそれを行いません。 constは嘘です!

Constは、実際に使用できるという保証はありません。 constをとるメソッドがあるとします。 2人のコード作成者がいます:callerを書く人とcalleeを書く人。呼び出し先の作成者は、メソッドにconstを取得させました。 2人の著者は、オブジェクトに関して不変であると仮定できますか?

なし。呼び出し先はconstを自由にキャストしてオブジェクトを変更できるため、呼び出し元にはguaranteeがありません。constをとるメソッドを呼び出しても実際には変更されません。同様に、呼び出し先は、呼び出し先のアクション全体でオブジェクトの内容が変更されないことを想定できません。呼び出し先は、constオブジェクトのnon const aliasでいくつかの変更メソッドを呼び出すことができます。これで、いわゆるconstオブジェクトはchangedになります。

Cスタイルのconstは、オブジェクトが変更されないことを保証しないため、壊れます。現在、Cにはすでに、必要に応じてdoubleをintに再解釈キャストできる弱い型システムがあります。そのため、constに関しても弱い型システムがあることは驚くべきことではありません。しかし、C#はgood型システム、つまり「この変数に文字列が含まれている」と言うときに変数が実際に文字列への参照を含む(またはnull)。 タイプシステムを嘘にしたくないなので、Cスタイルの "const"修飾子をタイプシステムに入れたくありません。型システムをstrongにして、コードについて理由にできるようにします。

Cの定数はguideline;です。それは基本的には「このことを変えようとしないことを私に信頼できる」という意味です。それはtype system;にあるべきではありません。 type systemの内容は、guidelineではなく、その使用法について推論できるオブジェクトに関するfactである必要があります。

誤解しないでください。 Cのconstが深く壊れているからといって、概念全体が役に立たないというわけではありません。私が見たいと思うのは、実際にはcorrectおよびseful C#の「const」アノテーションの形式です。 、ランタイムが自動並列化やその他の高度な最適化などを行うために使用できること。

たとえば、コードの塊の周りに「ボックスを描いて」、「I guaranteeこのコードの塊はこのクラスのどのフィールドにも変更を加えない」と言うことができると想像してください。コンパイラーによってチェックされます。または、「this pureメソッドはオブジェクトの内部状態を変更しますが、ボックスの外側で観察可能な方法ではない」というボックスを描画します。このようなオブジェクトは安全に自動的にマルチスレッド化できませんでしたが、自動的にメモできます。豊富な最適化とより深い理解を可能にするコードに付けることができる、あらゆる種類の興味深いアノテーションがあります。 弱いCスタイルのconstアノテーションよりも優れた方法があります。

ただし、これは単なる投機であることを強調します。この種の機能をC#の仮想の将来のバージョンに組み込む予定はありません。1つでもありますが、何らかの形で発表していません。それは私が見たいものであり、マルチコアコンピューティングの今後の重要性が必要とするかもしれないものですが、これはC#の特定の機能または将来の方向性を予測または保証するものではありません。

必要なのが、「このパラメーターの値はメソッド全体で変更されない」というパラメーターであるローカル変数の単なる注釈である場合、それは簡単に実行できます。一度初期化される「読み取り専用」ローカルとパラメーター、およびメソッドで変更するコンパイル時エラーをサポートできます。 「using」ステートメントで宣言された変数は、すでにそのようなローカルです。すべてのローカル変数とパラメーターにオプションの注釈を追加して、変数を「使用する」ように動作させることができます。非常に優先度の高い機能ではなかったため、実装されたことはありません。

59
Eric Lippert

C#にconst correctnessがない理由の1つは、ランタイムレベルに存在しないためです。 C#1.0は、ランタイムの一部でない限り、機能を持たないことに注意してください。

また、CLRにconstの正確性の概念がない理由はいくつかあります。

  1. ランタイムが複雑になります。さらに、JVMにもそれがなく、CLRは基本的に、C++のようなランタイムではなく、JVMのようなランタイムを作成するプロジェクトとして開始されました。
  2. 実行時レベルでconstの正確性がある場合、BCLにconstの正確性があるはずです。そうでなければ、.NET Frameworkに関する限り、この機能はほとんど無意味です。
  3. しかし、BCLがconstの正確性を必要とする場合、CLR上のすべての言語がconstの正確性(VB、JavaScript、Python、Ruby、F#など)をサポートする必要があります。not起こります。

定数の正確性は、C++にのみ存在する言語機能です。そのため、CLRがチェック済み例外を必要としない理由(Java言語のみの機能)と同じ議論に要約されます。

また、下位互換性を損なうことなく、このような基本的な型システム機能を管理された環境に導入できるとは思いません。そのため、C#の世界にconstが正確に入らないことを期待しないでください。

23
Ruben

C#がconst-correctではない2つの理由があると思います。

最初は理解度です。 const-correctnessを理解しているC++プログラマはほとんどいません。 const int argの簡単な例はかわいいですが、char * const * const argも見てきました-非定数文字への定数ポインターへの定数ポインター。関数へのポインターのconst-correctnessは、まったく新しいレベルの難読化です。

2番目は、クラス引数が値によって渡される参照であるためです。これは、明らかに明確な構文なしで、対処する2つのレベルの安定性があることを意味します。同様の障害は、コレクション(およびコレクションのコレクションなど)です。

定数の正確性は、C++型システムの重要な部分です。理論的には、コンパイル時にのみチェックされるものとしてC#に追加できます(CLRに追加する必要はなく、constメンバーメソッドの概念が含まれていない限り、BCLには影響しません) 。

しかし、これはありそうもないと思います。2番目の理由(構文)を解決するのは非常に難しく、それが最初の理由(理解度)をさらに問題にします。

11
Stephen Cleary

constはC#の「コンパイル時定数」を意味し、C++のように「読み取り専用ではなく、他のコードで変更可能」ではありません。 C#のC++ constの大まかな類似はreadonlyですが、これはフィールドにのみ適用できます。それ以外に、C#にはconstの正確性に関するC++のような概念はまったくありません。

多くの潜在的な理由があるため、理論的根拠を確実に伝えることは困難ですが、私の推測では、言語を何よりもシンプルに保ち、この2番目を実装することの不確実な利点を維持したいでしょう。

5
Pavel Minaev