C#コードでポインターを使用する必要がありますか?メリットは何ですか?The Man(Microsoft)が推奨していますか?
11 に答える
「男」自身から:
C#でポインターを使用する必要があることはめったにありませんが、ポインターを必要とする状況がいくつかあります。例として、安全でないコンテキストを使用してポインターを許可することは、次の場合に保証されます。
- ディスク上の既存の構造を処理する
- ポインターを含む構造を含む高度なCOMまたはプラットフォーム呼び出しシナリオ
- パフォーマンスが重要なコード
他の状況で安全でないコンテキストを使用することはお勧めしません。
具体的には、安全でないコンテキストを使用してCコードをC#で記述しようとしないでください。
注意:
安全でないコンテキストを使用して記述されたコードは安全であると検証できないため、コードが完全に信頼されている場合にのみ実行されます。つまり、信頼できない環境で安全でないコードを実行することはできません。たとえば、安全でないコードをインターネットから直接実行することはできません。
あなたがしなければならない場合。
大きなグレースケール画像、たとえば2000x2000ピクセルを偽色にする必要があるとします。GetPixel()
まず、とを使用して「安全な」バージョンを記述しSetPixel()
ます。それがうまくいけば、素晴らしいです、先に進んでください。それが遅すぎることが判明した場合は、画像を構成する実際のビットを取得する必要があるかもしれません(例のためにカラーマトリックスを忘れてください)。安全でないコードを使用することについて「悪い」ことは何もありませんが、プロジェクトが複雑になるため、必要な場合にのみ使用する必要があります。
そうしなければならなかったことを今まで覚えていませんが、相互運用はあまり行っていません。これが最も一般的なアプリケーションだと私は信じています。ネイティブコードを呼び出すことです。ポインターを使用してコードを最適化できることはほとんどありませんが、私の経験では非常にまれです。
ガイドであれば、C#の経験は豊富だと思いますが、安全でないコードを実行する必要がある場合は、spec / books/MSDNを参照してガイドする必要があります。もちろん、安全でないコードには満足しているが、(たとえば)クエリ式にはあまり慣れていない人はたくさんいます...
主な問題は次のとおりです。
- 安全でないコードは検証できません。これは、ユーザーが完全に信頼されたコンテキストからのみコードを実行できることを意味します。したがって、ユーザーが完全に信頼されていない場所 (たとえば、そのように構成されていないネットワーク共有) からコードを実行する必要がある場合は、ねじ込んだ。
- 検証可能性の欠如 (それが実際に単語かどうかはわかりません)は、プログラムでメモリを台無しにする可能性があることも意味します。バグのクラス全体をアプリケーションに戻す可能性があります-バッファーオーバーラン、ダングリングポインター、ヤダヤダヤックヤック。ポインタがおかしくなったときに気づかずに、メモリ内のデータ構造を破損する可能性があることは言うまでもありません。
- 安全でないコードがマネージド オブジェクトにアクセスできるようにするには、それらを「固定」する必要があります。これは、GC がメモリ内でオブジェクトを移動することを許可されていないため、マネージ ヒープが断片化される可能性があることを意味します。これにはパフォーマンスへの影響があります。したがって、潜在的なパフォーマンスの向上がこの問題を上回っていないかどうかを判断することは常に重要です。
- アンマネージド アプローチに慣れていないプログラマーにとって、コードは理解しにくくなります。その場合、安全でないコードが提供する「自由」の一部に足を踏み入れる可能性が高くなる可能性があります。
- タイプセーフでないコードを記述できるようになります。これはむしろ、素敵なウォーム ファジー マネージ言語の多くの利点を排除します。これで、恐ろしいタイプの安全性の問題に遭遇する可能性があります。なぜその一歩を後退させるのですか?
- それはあなたのコードを醜くします。
リストに追加できるものは他にもあると確信しています。一般に、他の人が言ったように、特別なポインターファンクを必要とする p/invoke を介してアンマネージメソッドを呼び出す必要がない限り、避けてください。それでも、マーシャラーはほとんどの場合、その必要性をほとんど防ぎます。
「男」も基本的には必要がなければ避けると言います。
ところで、MSDN にここにピン留めすることについての素晴らしい記事があります。
安全でないコードは、.NETCLRで完全にサポートされている機能です。利点は、パフォーマンスとバイナリコードとの互換性です。ランタイムは、クラッシュや書き込みを防ぐサンドボックスですが、コストがかかります。画像操作など、メモリ内の大きなブロブに対して非常に集中的な操作を実行している状況では、ランタイムが提供する通常の安全性から外れる方が高速です。
そうは言っても、ここのほとんどの人は「やらないで」と言うだろうと思います。.NET開発者の大多数は、安全でないコードを使用することによってのみ解決できる通常の活動でケースに遭遇することはありません。
安全でないコードを使用してなりすましを使用し、サービスがネットワーク共有にアクセスできるようにしました。自分が何をしているのかを知っていれば問題ありません。
必要な場合はそれらを使用する必要があります。ほとんどの場合、これはいくつかのトリッキーな相互運用シナリオを処理する場合に発生します(たとえば、.NET 1.0でDPAPIのマネージラッパーを作成した場合、それらが必要でした)が、非常にまれに、stackalloc
または同様のものを使用してパフォーマンスを向上させる場合があります(プロファイリング後!)。
彼らがC#の設計者である限り、それはMicrosoftによって推奨されており、彼らはunsafe
それにコードを書く機能を追加することを決定しました。キーワードの選択と、キーワードを使用してそれを記述するメソッド/クラスを描写するための要件から、それが事実上の実装の選択になるように設計されていないことがわかります。
BitConverter によって提供されないキャストのような再解釈。
具体的には、気にするのはビットだけであるハッシュ関数の unint を int に変換します。
よく知られている長さの byte* として処理する必要がある構造体で、c または C++ の慣用関数について十分に推論された有用ないくつかの関数を使用します。これも、ハッシュに最も役立ちます。
メモリ構造体の (非常に具体的な) 非常に高速なバイナリ シリアル化 (それらの配列に対して実行することによる) ですが、正直なところ、これは C++/CLI にドロップするだけでより適切に実行できます。
多くの場合、ポインターを必要とするタスクは、C++/CLI で実行し、これを c# プロジェクトに dll としてインポートすることで、より適切に解決できることが多いと言わざるを得ません。コードが「安全」かどうかは変わりませんが、ポインターベースの構造を操作するための便利な関数の束がよりアクセスしやすくなります。また、本当に必要な場合は、ジェネリック型または列挙型をいじることもできます。
ほとんどの開発者がこれを行う必要がある可能性は、実際にはほとんどありません。いざという時に便利ですが…
もちろん、「推奨」ではないため、「安全ではない」というラベルが付けられています。しかし、それであなたを怖がらせないでください。ただし、コードを2回見る必要があります。おそらくそれを行うための管理された方法がありますか?
安全でないコードを使用することは、.Net Frameworkの利点を忘れるようなもので、スタックなどの昔ながらの構造を作成するために一度使用しましたが、それは学校専用でした。今日では、それらを使用する必要はありませんでした。
コードをより短く、より明確にする場合は、それを行ってください。
「角を曲がったところにいる警官に十分配慮して、あなたの傾向に従ってください。」WSM