web-dev-qa-db-ja.com

C#でポインター(安全でないコード)を使用する必要がありますか?

C#コードでポインターを使用する必要がありますか?メリットは何ですか? The Man(Microsoft)が推奨していますか?

43
Kredns

「TheMan」自身から:

C#でポインターの使用が必要になることはめったにありませんが、ポインターが必要な状況がいくつかあります。例として、安全でないコンテキストを使用してポインターを許可することは、次の場合に保証されます。

  • ディスク上の既存の構造を処理する
  • 高度なCOMまたはPlatformInvokeシナリオには、ポインターを含む構造が含まれます
  • パフォーマンスが重要なコード

他の状況で安全でないコンテキストを使用することはお勧めしません。

具体的には、安全でないコンテキストを使用してC#でCコードを記述しようとしないでください。

注意:

安全でないコンテキストを使用して記述されたコードは安全であると検証できないため、コードが完全に信頼されている場合にのみ実行されます。つまり、安全でないコードは、信頼できない環境では実行できません。たとえば、安全でないコードをインターネットから直接実行することはできません。

参照

36
nzpcmad

あなたがしなければならない場合。

大きなグレースケール画像、たとえば2000x2000ピクセルを偽色にする必要があるとします。まず、GetPixel()SetPixel()を使用して「安全な」バージョンを記述します。それがうまくいけば、素晴らしいです、先に進んでください。それが遅すぎることが判明した場合は、画像を構成する実際のビットを取得する必要があるかもしれません(例のためにカラーマトリックスを忘れてください)。安全でないコードを使用することについて「悪い」ことは何もありませんが、プロジェクトが複雑になるため、必要な場合にのみ使用する必要があります。

21
Ed S.

そうしなければならなかったことを今まで覚えていませんが、相互運用はあまり行っていません。これが最も一般的なアプリケーションだと私は信じています。ネイティブコードを呼び出すことです。ポインタを使用してコードを最適化できることはほとんどありませんが、私の経験では非常にまれです。

ガイドであれば、C#の経験はかなりあると思いますが、安全でないコードを実行する必要がある場合は、spec/books/MSDNを参照してガイドする必要があります。もちろん、安全でないコードには満足しているが、(たとえば)クエリ式にはあまり慣れていない人はたくさんいます...

12
Jon Skeet

主な問題は次のとおりです。-

  • 安全でないコードは検証できません。つまり、コードは完全に信頼できるコンテキストからユーザーがのみ実行できるため、ユーザーがどこからでもコードを実行する必要がある場合は、完全に信頼されている(たとえば、ネットワーク共有がそのように構成されていない)よりも、あなたは困惑しています。
  • 検証可能性の欠如(それが実際にWordであるかどうかはわかりません)は、プログラムのメモリを潜在的に台無しにする可能性があることも意味します。あなたは潜在的にバグのクラス全体をアプリケーションに戻しています-バッファオーバーラン、ダングリングポインタ、ヤダヤダヤックヤック。ポインタがおかしくなったことに気付かずに、メモリ内のデータ構造を破壊できる可能性があることは言うまでもありません。
  • 安全でないコードが管理対象オブジェクトにアクセスするようにしたい場合は、それらを「固定」する必要があります。これは、GCがオブジェクトをメモリ内で移動することを許可されていないため、マネージヒープが断片化される可能性があることを意味します。これにはパフォーマンスへの影響があります。したがって、潜在的なパフォーマンスの向上がこの問題を上回っていないかどうかを判断することは常に重要です。
  • アンマネージドアプローチに慣れていないプログラマーにとっては、コードが理解しにくくなります。その場合、彼らは、安全でないコードが彼らに与える「自由」のいくつかで彼らの足を撃ち落とす傾向があります。
  • 型安全でないコードを書くことができるようになります。これは実際には、ニースのウォームファジーマネージド言語の多くの利点を排除します。今、あなたは恐ろしいタイプの安全性の問題に遭遇する可能性があります。なぜその一歩後退するのですか?
  • それはあなたのコードを醜いにします。

リストに追加できるものは他にもあると思います。一般的に、他の人が言っているように-あなたがしなければならない場合を除いて避けてください。特別なポインタファンキングを必要とするp/invokeを介してアンマネージメソッドを呼び出す。それでも、マーシャラーはほとんどの場合、その必要性を防ぎます。

「男」も基本的に必要な場合を除いて避けると言います。

ああ、ピン留めについての素晴らしい記事 ここMSDNで ちなみに。

6
ljs

安全でないコード は、.NETCLRで完全にサポートされている関数です。利点は、パフォーマンスとバイナリコードとの互換性です。ランタイムは、クラッシュや書き込みを防ぐサンドボックスですが、コストがかかります。画像操作など、メモリ内の大きなblobに対して非常に集中的な操作を実行している状況では、ランタイムが提供する通常の安全性から外れる方が高速です。

そうは言っても、ここのほとんどの人は「やらないで」と言うだろうと思います。 .NET開発者の大多数は、安全でないコードを使用することによってのみ解決できる通常のアクティビティでケースに遭遇することはありません。

3
Rex M

安全でないコードを使用して偽装を使用し、サービスがネットワーク共有にアクセスできるようにしました。自分が何をしているのかを知っていれば問題ありません。

3
Otávio Décio

BitConverterによって提供されていないキャストのような再解釈。
具体的には、unintをハッシュ関数のintに変換します。ここで、気になるのはビットだけです。

構造体でcまたはC++の慣用関数について、よく知られている長さのバイト*として扱う必要がある場合に、いくつかの有用で十分な理由のある関数を使用します。これもハッシュに最も役立ちます。

正直なところ、これはC++/CLIにドロップするだけで実行できますが、メモリ構造体の(非常に具体的な)バイナリシリアル化は(それらの配列に対して実行することにより)非常に高速です。

多くの場合、ポインターを必要とするタスクは、C++/CLIで実行し、これをdllとしてc#プロジェクトにインポートすることで、より適切に解決できることが多いと言わなければなりません。コードが「安全」であるかどうかは変わりませんが、ポインタベースの構造を操作するための便利な関数がたくさんあります。また、本当に必要な場合は、ジェネリック型や列挙型をいじることもできます。

ほとんどの開発者がこれを行う必要がある可能性は確かに低いです。必要なときに便利ですが...

2
ShuggyCoUk

必要な場合はそれらを使用する必要があります。ほとんどの場合、これはいくつかのトリッキーな相互運用シナリオを処理する場合に発生します(たとえば、.NET 1.0でDPAPIのマネージラッパーを作成した場合、それらが必要でした)が、stackalloc または類似。

C#の設計者である限り、Microsoftによって推奨されており、unsafeコードを書き込む機能を追加することを決定しました。キーワードの選択と、キーワードを使用してそれを記述するメソッド/クラスを描写するための要件から、それが事実上の実装の選択になるように設計されていないことがわかります。

2
Greg Beech

コードが短く明確になる場合は、それを実行してください。

「角を曲がった警官に十分な注意を払ってあなたの傾向に従ってください。」 [〜#〜] wsm [〜#〜]

1
daonb

もちろん、「推奨」ではないため、「安全ではない」というラベルが付けられています。しかし、それがあなたを怖がらせないでください。ただし、コードを2回見る必要があります。おそらくそれを行うための管理された方法がありますか?

1
Al W

安全でないコードを使用することは、.Net Frameworkの利点を忘れるようなものです。スタックなどの昔ながらの構造を作成するために一度使用しましたが、それは学校専用でした。最近は、それらを使用する必要がありませんでした。

1
Oscar Cabrero