0

最近、SOに関するスレッドがほとんどありませんでした(以下)。一般的な提案の1つは、ポインターを使用しないことでした。

.netの固定ブロック

.NETでは、関数パラメーターとしてポインターを使用することと、「ref」キーワードを使用することの間に違いはありますか?

.netの文字列は変更されますか?バグはありますか?

最近、ビットマップ画像の白い背景を透明に変換する必要がありました。私は試してみましたが、思いついた最適な実装は以下のとおりです。

public unsafe Bitmap MakeWhiteAreaTransparent(Bitmap source)
{
    Bitmap bitmap = new Bitmap(source.Width, source.Height, PixelFormat.Format32bppArgb);
    BitmapData bitmapdata = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
    BitmapData data2 = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
    int* numPtr = (int*)bitmapdata.Scan0;
    int* numPtr2 = numPtr + (bitmapdata.Width * bitmapdata.Height);
    int* numPtr3 = (int*)data2.Scan0;
    int num = Color.FromArgb(1, Color.White).ToArgb();
    while (numPtr < numPtr2)
    {
        numPtr++;
        Color color = Color.FromArgb(numPtr[0]);
        if (((color.R < 200) || (color.G < 200)) || (color.B < 200))
        {
            numPtr3[0] = color.ToArgb();
        }
        else
        {
            numPtr3[0] = num;
        }
        numPtr3++;
    }
    source.UnlockBits(bitmapdata);
    bitmap.UnlockBits(data2);
    return bitmap;
}

私はポインターを訴えるのが正しいのか、それともバイト配列とSystem.Runtime.InteropServices.Marshal.Copyを使用するべきであり、ポインターをいじくり回すのではないのか疑問に思っていました。

4

2 に答える 2

2

安全でないコードを使用しても、まったく問題はありません。仕事に適したツールを使用します。安全でないコードとポインターのサポートは言語に組み込まれています。つまり、開発者はそれが便利なものであると考えていました。他の機能の実装を犠牲にして実装するのに十分なほど便利です。

安全でないコードの場所があります。お気づきのように、これはビットマップ イメージの生データにアクセスする最速の方法です。はい、安全なコードでそれを行う方法はありますが、かなり遅くなります。アンセーフ コードは、2 ギガバイトを超えるメモリ バッファーを操作する唯一の方法でもあります。

そして、確かに、サイズが数ギガバイトの単一オブジェクトが実際に必要なアプリケーションがあります。これについては好きなように異議を唱えることができます。私は、80 年代に「1 メガバイトの RAM が必要な人がいるでしょうか?」などと言った馬鹿を笑ったように、あなたを笑い飛ばします。

アンセーフ コードが必要な場合は、C++ でネイティブ DLL を作成し、.NET プログラムから呼び出す必要があると言う人もいます。それはばかげた考えです。まず、ネイティブ DLL を構築するためのツールや知識がない可能性があります。次に、プロジェクトに依存関係が追加されます。第三に、特別な利点はありません。「より安全」ですか?いいえ。

仕事を成し遂げるために必要なものを使用してください。安全なコードを使用するためにあらゆる努力をしてください。しかし、他のすべてを試した後で、必要なことにアンセーフ コードが必要であることがわかった場合は、それを使用してください。そのため、そのサポートがプラットフォームに追加されました。

于 2012-04-20T16:07:21.183 に答える
2

私の意見は次のとおりです。言語は本来の使用方法で使用する必要があります。C# は安全なコードで使用されることになっているため、一部のコードが非常に高速である必要があり、頻繁に呼び出される場合、最後の手段として安全ではありません。

いくつか例を挙げてみましょう。

  1. 低速な操作を行う必要がありますが、バックグラウンドでどこかで実行することができますが、それほど頻繁ではなく、その速度はそれほど重要ではありません。この場合、安全なコードを使用できます。このアプローチは、プロセッサからパフォーマンスの最後のビットを絞り出すことはないかもしれませんが、実装と (より重要な) メンテナンスの労力が大幅に軽減されます。

  2. 操作を高速化する必要があります。安全な実装は容認できないほど遅いです。そして、アルゴリズムを改善しようとしましたが、最善を尽くしましたが、それでも遅いです。試してみると、アンマネージ実装の方がかなり高速であることがわかりました。.NET は、コードのその部分を正確に実装するのに適したプラットフォームではありません。ネイティブ DLL またはプラットフォームで利用可能なもの (おそらく純粋な C) でコードを実装し、P/Invoke を介して使用します。このようにして、アンセーフ コードは適切な言語でコーディングされ、P/Invoke によってメソッドを呼び出すか、C++/CLI ラッパーを追加するか、C# で相互運用を行うその他の方法でメソッドを使用することができます。(1) 管理されたビジネス ロジックとネイティブの非常に高速な処理コードとの間の明確な分離、(2) 高速な数値演算またはデータ シャッフル コードが適切な環境にあるため、保守性が向上します。

  3. さて、そのアプローチでさえ何らかの理由で機能しないことがわかります。この例外的なケースでは、C# でアンセーフ コードを使用することを検討する必要があります。しかし、これでも役に立たない可能性が高いです。

于 2012-04-20T14:33:38.950 に答える