2009-02-24 10 views
39

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

+0

ポインタの使用は、一般的にp/invokeに関係します。この記事を参照してください:http://www.c-sharpcorner.com/UploadFile/pcurnow/usingpointers10022007082330AM/usingpointers.aspx – gsscoder

+0

特定の用途に安全でないコードを頻繁に使用している場合は、安全なパブリッククラスに含まれるプライベート内部クラスのコード。私はアプリケーションの残りの部分がポインタを扱うという考えが嫌いです。次に、不明なバグは、アプリケーションの残りの部分ではなく、このクラスのペアにトレースされます。追加された複雑さがコードベースの残りの部分に漏れるのを防ぎます。 – Nuzzolilo

答えて

35

ポインタの使用はほとんどC#で必要ありませんが、それらを必要とするいくつかの状況がありますされています。ポインタを許可するように危険なコンテキストを使用しての例は、次のような場合によって保証されたよう:

  • ディスク上の既存の構造と
  • 高度なCOMまたはプラットフォーム呼び出しのシナリオを扱い、それらにポインタを持つ構造体を伴う
  • パフォーマンス - クリティカルコード

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

具体的には、安全でないコンテキストを使用してC#でCコードを書き込もうとするべきではありません。

注意:危険なコンテキストを使用して書かれた

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

Reference

+1

通常、インターネット上の例で安全でないC#コードが表示されている場合、それはコードの匂いです。意味、誰かがC#でCコードを書こうとしました。この時点で、Managed.Interop名前空間はかなり拡張されており、IntPtrを単一インスタンスの構造体にラップすることができます。そのため、安全でないのはCLRの専門家によるパフォーマンス重視のコードです。管理された世界でポインタを使って古いトリックを維持する方法ではありません。 –

11

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

もしそれがガイドであれば、私はC#でかなり経験があると思いますが、安全でないコードを実行する必要がある場合は、スペック/書籍/ MSDNで相談してください。もちろん、安全でないコードに満足していても、クエリ式に慣れていない人がたくさんいます。

+6

私は多くの画像処理を行い、LockBitsは私に多くの労力をかけてくれました。私は他の場所で安全ではないコードを使用したことはありません。 –

+0

私は時々それを使用しましたが、interopでさえほとんど使用しませんでした。私たちは16ビットのTWAINをラップし、安全でないコードではなくIntPtrだけを使用しなければなりませんでした。私がビットマップ操作のために使用したと思った場所だけが、メモリを固定することができました。 –

+1

これまでに私が使用したのは画像操作用の唯一の時間です。私は画像の特定の部分を反転させなければならず、安全でないコードがなければそれは顕著な遅れを持っていましたが、安全でないコードでは<1 msで終了しました。 –

2

必要に応じて使用してください。 (例えば、.NET 1.0でDPAPI用の管理されたラッパーを作成したときなど)は、stackallocなどを使用してパフォーマンスを向上させることがあります(プロファイリング後に)場合があります。

マイクロソフトでは、C#の設計者と同じくらいお勧めしており、unsafeコードを書く機能を追加することを決定しました。キーワードの選択と、キーワードを使用して記述するメソッド/クラスを記述するための要件から、事実上の実装の選択肢ではないことがわかります。

1

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

3

Unsafe codeは、.NET CLRの完全にサポートされている機能です。利点はパフォーマンスとバイナリコードとの互換性です。ランタイムはクラッシュや燃焼を防ぐサンドボックスですが、それにはコストが伴います。たとえば画像操作など、メモリ内の大きなブロブに対して非常に集中的な操作を行っている状況では、ランタイムが提供する通常の安全性を超えて踏み出すほうが速くなります。

これまでに言われたことは、私が考えているのは、で、ほとんどの人が「」と言う人は「do not do it」と言います。大多数の.NET開発者は、安全でないコードを使用することによってのみ解決できる正常な活動のケースに踏み込むことはありません。

19

する必要がある場合。

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

+0

画像を扱うことは、おそらく、パフォーマンスの向上をもたらすために安全でないコードを使用する際に最も一般的に使用されることに注意してください。しかし、 'unsafe'と' LockBits'に行く前に 'LockBits'を使うべきだと主張します。 – TheLethalCoder

+0

@ TheLethalCoder:あなたが経験を持っていない場合は、多分、おそらく、。それが必要かどうかを知る前に作業を済ませたら。時期尚早の最適化ではありません。 –

+1

私はもっと同意できませんでした。あるプラットフォームから別のプラットフォームにイメージを変換することを検討してください。イメージはそれぞれ異なるクラスとフォーマットを使用しています。配列をコピーして、それを反復して変換し、それをターゲットにコピーするか、ポインタを使用してソースからデスティネーションまで1回のパスでコピー&変換することができます。あなたが何をしているのかを知っているなら、「安全な」方法は大いに非効率的です。 – Daniel

3

私はサービスにネットワーク共有へのアクセスを許可するために偽装を使用するために安全でないコードを使用しました。あなたがしていることを知っていれば問題ではありません。 「男」自分自身から

1

の.NET Frameworkのbenenfitsを忘れるようなもので、私は、スタックやもののように作成した、昔ながらの構造に一度、それらを使用するが、それは唯一の学校のためだった、最近は私がする必要があったhaventはそれらを使用してください。

1

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

「コーナーの周りの警察官を尊重して、あなたの傾向に従ってください。」 WSM

+0

ポインタは自分自身を繰り返すことと何が関係していますか? –

+0

安全でないコードブロックを安全性の高い.NETアプリケーションに投げ込まないでください。私はあなたがC/C++を誤解していると思います。これは以前のバージョンであったが、ネイティブコードよりもはるかに高速で信頼性が高くなっている。特に、そこに膨らみがほとんどないLinuxシステムでは、実際には、私のC++アプリケーションよりLinuxの.NETアプリケーションが高速に動作する。 。 – osirisgothra

2

BitConverterで提供されていない、再解釈可能なキャストです。
具体的には、あなたが心配するのがビットであるハッシュ関数の場合、unintをintに変換します。

よく知られている長さのバイト*として扱う必要がある構造体について、便利なCまたはC++の慣用的な関数を使用します。これはハッシュに最も便利です。

メモリ構造体(非常に特定)の非常に高速なバイナリシリアル化(それらの配列に行うことにより)は正直言っても、これはC++/CLIにドロップするほうが良いです。

多くの場合、ポインタを必要とするタスクは、C++/CLIでそれを行い、これをdllとしてC#プロジェクトにインポートすることで、しばしば解決することができます。コードが安全であるかどうかは変わりませんが、ポインタベースの構造で操作するための便利な機能がたくさん用意されています。また、本当にしたい場合はジェネリック型や列挙型を混乱させることができます。

これを行う必要があるほとんどの開発者の可能性は、実際には遠いです。便利なあなたがそれを必要とするときけれども...

5

私は主な問題であると言うでしょう: -

  • 安全でないコードが検証可能ではありません。つまり、コードはのみが完全に信頼できるコンテキストからユーザーによって実行されることができることを意味します。したがって、完全に信頼できる場所からコードを実行する必要がある場合(たとえば、やめた
  • 検証可能性の欠如(実際には単語であるかどうかは分かりません)は、の可能性があります。がプログラム内でメモリを駄目にする可能性があります。 バッファオーバーラン、ポインタの絡み、yada yada yuck yuckなど、バグのクラス全体をアプリケーションに戻す可能性があります。あなたのポインタが変わったときに実現することなく、潜在的にメモリ内のデータ構造を破壊する可能性があることは言うまでもありません。
  • あなたの安全でないコードが管理対象オブジェクトにアクセスするようにするには、それらを「ピン止め」する必要があります。これは、GCがあなたのオブジェクトをメモリ内で動かすことを許可されていないことを意味します。したがって、管理されたヒープが断片化する可能性があります。これにはパフォーマンスに影響があります。したがって、潜在的なパーセンテージがこの問題によって上回らないかどうかを判断することは常に重要です。
  • アンマネージドアプローチに慣れていないプログラマーにとっては、コードが理解しづらくなります。彼らは、「自由」な安全でないコードのいくつかを使って足を踏み外してしまう可能性がより高いかもしれません。
  • un-type-safeコードを書くことができるようになりました。これはむしろ暖かいファジーマネージド言語の利点をかなり排除します。今では恐ろしい型の安全問題に遭遇することがあります。なぜそのステップを逆にするのか?
  • あなたのコードはuglierになります。

リストに追加できる数が増えていると確信しています。一般的には、他人の言っているように - あなたがしなければ避けてください。特殊なポインタのファンクションを必要とするp/invokeによってアンマネージドメソッドを呼び出すたとえそうであっても、マーシャルは主にそれを必要としないようにするでしょう。

「男は基本的に必要な場合を除き、避けてください。

ちなみにピン固定については、here on MSDNです。

+0

通常、(完全な信頼の下で)検証者は無効になっています。つまり、あなたの '安全性'は実際に正しく機能するためにコンパイラに依存します。基本的に、安全でないアクションを実行するILを作成することができます –

関連する問題