8

私はポインターを理解しており、C#コードでポインターを使用する必要はほとんどありません。私の質問は、コードのブロックで「安全でない」と明示的に述べなければならない理由は何ですか。さらに、「安全でない」コードを許可するためにコンパイラオプションを変更する必要があるのはなぜですか?

結論: CLR(または言語仕様)の何が原因で、「unsafe」と入力してコンパイラオプションを変更せずに、いつでも(CやC ++のように)ポインタを使用できないようになっていますか?

明確にするために:私は「安全でない」および「安全な」コードが何であるかを知っています。これらの機能を使用できるようにするためだけに、なぜすべての余分な作業を実行する必要があるのか​​(それほど余分な作業ではありません)の問題です。

4

9 に答える 9

9

C# の作成者である Anders Hejlsberg とのインタビューで、この件に触れています。基本的に、@Marc Gravellが言ったこととまったく同じです:タイプセーフが最初で、明示的な宣言による安全性がありません。

だからあなたの質問に答えるために:CLRにはそれを妨げるものは何もありません。これは、型を扱うときに安全手袋を着用して作業できるように設計された言語イディオムです。手袋を外したい場合はあなたの選択ですが、手袋を脱ぐには積極的な選択をしなければなりません。

編集:

明確にするために:「安全でない」コードと「安全な」コードが何であるかを知っています。これらの機能を使用できるようにするためだけに、なぜ余分な作業をすべて行わなければならないのかという問題です (わかりました、それほど余分ではありません)。

リンクしたインタビューで述べたように、これは明示的な設計上の決定でした。C# は本質的に Java の進化形であり、Java ではポインターがまったくありません。しかし、設計者はポインターを許可したいと考えていました。ただし、C# は一般的に Java 開発者を呼び込むため、明示的な宣言によるポインターの使用を許可しながら、デフォルトの動作が Java に似ている、つまりポインターがないことが最善であると彼らは感じました。

したがって、「余分な作業」は、実行する前に自分が何をしているのかを考えさせるために意図的に行われます。明示的であることにより、少なくとも次のことを考慮する必要があります。

于 2009-03-03T16:46:52.527 に答える
7

それは主に検証可能であることについてです。と述べることunsafeで、手袋が外れます-システムは、コードが正常に実行されないことを保証できなくなります。ほとんどの場合、セーフゾーンにとどまることが非常に望ましいです。

これは部分的な信頼(アドインなど)でより顕著になりますが、通常のコードでは依然として価値があります。

于 2009-03-03T16:40:24.133 に答える
3

実際、CLR は /unsafe スイッチまたはキーワードについてまったく要件を設けていません。実際、C++/CLI (CLR の下で実行される C++ 言語) にはそのような /unsafe スイッチはなく、ポインターは CLR で自由に使用できます。

したがって、私はあなたの質問を「ポインタを使用する前に C# で /unsafe を使用する必要があるのはなぜですか?」と言い換えます。そして、その質問に対する答えは、ここに記載されている他の回答に記載されているとおりです。ユーザーが、CLR で完全信頼モード以外で実行する機能を失うという意識的な決定を下せるようにするためです。C++ は事実上常に CLR で完全な信頼を必要とし、C#完全な信頼を必要とするコードを呼び出すとき、またはポインターを使用するときはいつでも可能です。

于 2009-03-03T16:57:32.610 に答える
2

安全でないブロックを使用すると、コードを検証不能にする効果があります。これを実行するには特定の権限が必要であり、出力で許可したくない場合があるため(特に共有ソース環境にいる場合)、コンパイラに許可しないスイッチがあります。

于 2009-03-03T16:41:33.117 に答える
2

要するに、.NET はユーザーが意図を表明することを望んでいます。

確かに、コンパイラは「安全でない」フラグの必要性を推測できます。しかし、設計者はそれが慎重な決定であることを望んでいます。

私にとって、これは C# の多くの構文要件に似ています。

  • ノースイッチケースノーブレイク
  • アクセスレベルの「セクション」がない (C++ の「public:」マーカーなど)
  • 「var」を使用するクラス フィールドはありません

あるものを動かしたり変更したりして、うっかり別のものに影響を与えてはならないというのがパターンです。当然のことながら、彼らはあなたが「足を撃たれる」のを防ぎたいと思っています。

ここには有益で有益な回答がたくさんあります — おそらくこれはあなたの質問にもっと当てはまるでしょう.

于 2009-03-03T18:05:31.807 に答える
2

反対の観点から考えてみてください。安全でないとマークされていないため、ほとんどのコードはデフォルトで「安全」であると推測できます。では、「安全」とは何を意味するのでしょうか。.Net コードの場合、これには以下が含まれます (ただし、これらに限定されない場合があります)。

  • ガベージ コレクターは通常どおり業務を行うことができます。
  • 特定の型の参照は、その型 (または null) のオブジェクトを参照します。
  • コードは、.Net の信頼/セキュリティ要件に準拠することが保証されています。
  • このコードは、それ自身の AppDomain の外部のメモリに直接触れないことが数学的に証明されています。些細なことのように思えるかもしれませんが、同じアプリケーションに複数の AppDomain がある場合を想像してみてください。プログラマーは、自信を持ってそれらを論理的に分離して扱うことができます。

ポインターを使用するときはいつでも、これらの保証を破る可能性があります。したがって、コードを安全でないとマークすると、それらの保護が放棄されます。

于 2009-03-03T16:47:13.490 に答える
1

そのため、昇格された権限などがないと、どのコードがWebサービスで実行されないかがすぐにわかります。

于 2009-03-03T16:40:35.160 に答える
1

良い習慣と安全を育む。アセンブリで安全でないブロックを使用する場合は常に、スタックからNativeCode権限が要求されます。もちろんこれは暗黙的に行うこともできますが、privateキーワードを完全に削除することもできませんか?開発者が安全でないコードを使用する前に、それを特に要求するように強制するのは良いことだと思います。

于 2009-03-03T16:41:05.473 に答える
1

安全なコードと安全でないコードの最も大きな違いは、.net のガベージ コレクターが安全でないコードに到達できないことです。自動 GC は .net の用語の大きな部分を占めており、その境界を超えると、コードについて想定できる多くのことを変更します。

特にポインターを使用すると、GC 参照なしでヒープ上にオブジェクトを作成できます。これは、コードを「安全でない」とマークする必要があるもう 1 つの優れた理由につながります。メモリリークがあることに気付いたときに、どこからメモリリークが発生しているかを簡単に絞り込むことができます。

于 2009-03-03T16:47:57.763 に答える