10

デリゲートのC# ドキュメントでは、「デリゲートは、名前付きメソッドまたは匿名メソッドをカプセル化するために使用できる参照型です。デリゲートは C++ の関数ポインターに似ていますが、デリゲートはタイプセーフで安全です」

私の質問は、「安全な」デリゲートとはどういう意味ですか?

4

5 に答える 5

8

デリゲートは、メソッドへのタイプ セーフな呼び出しを強制します。これは通常、コンパイラによって実行される静的な型チェックによって機能します。唯一の方法ではありませんが、Delegate.DynamicInvoke()コンパイラの型チェックをバイパスするために使用できます。例:

using System;

class Program {
    delegate void foo(long arg);
    static void Main(string[] args) {
        var obj = new Example();
        var dlg = Delegate.CreateDelegate(typeof(foo), obj, "Target");
        dlg.DynamicInvoke(42);
    }
}

class Example {
    private long field;
    public void Target(long arg) {
        field = arg;
    }
}

次に、このコードをいじり始めます。これは、型システムをだますためにできることのようなものです。

  • foo デリゲート宣言を変更する
  • 第 1 引数として別のデリゲート タイプを渡す
  • 2 番目の引数として別のクラスのオブジェクトを渡します
  • ターゲット メソッド名を変更する
  • DynamicInvoke呼び出しで異なる型の引数を渡す
  • DynamicInvoke呼び出しで異なる引数のセットを渡す

これらの試みはすべて問題なくコンパイルされます。それらのどれも実行されず、実行時例外が発生します。これがデリゲートを安全にするものです。デリゲートを使用して、スタックを不均衡にしたままにするメソッドを呼び出したり、初期化されていない、またはアクティブ化フレームの一部ではないスタックの場所にアクセスするようにターゲット メソッドを誘導したりすることはできません。マルウェアがコードをハイジャックする従来の方法。C や C++ にはそのようなランタイム チェックは存在せず、コンパイラは静的チェックのみを実行し、単純なキャストでバイパスできます。

于 2012-07-07T15:25:28.797 に答える
5

私の質問は、デリゲートが「安全」であるとはどういう意味ですか?

デリゲートを使用して呼び出される関数には、呼び出し元のセキュリティ コンテキストが与えられます。これにより、権限の低い呼び出し元が利用できないタスクをデリゲートが実行できなくなります。デリゲートは、どこにでも実装されている関数へのポインターで初期化できます。唯一の制限は署名です。不明なソースへの関数ポインターを含むデリゲートを呼び出すときは、予期しない実装が発生する可能性があるため、呼び出し元は注意する必要があります。デリゲートを保護するには、コード アクセス セキュリティを使用します。

クレジット: http://etutorials.org/Programming/programming+microsoft+visual+c+sharp+2005/Part+III+More+C+Language/Chapter+8+Delegates+and+Events/

于 2012-07-07T14:24:21.787 に答える
2

このコンテキストでは、安全とは、デリゲートが無効な値を保持できないことを意味すると思います。これはおそらく、タイプセーフな部分と少し重なっています。

于 2012-07-07T14:18:07.560 に答える
2

これは、C/C++ のように、関数ポインターがメモリの無効な領域を指すようにしたり、悪意のあるコードを指すようにしたりすることができないことを意味します。

于 2012-07-07T14:19:06.253 に答える
2

男性が言ったように、それらを「足を吹き飛ばす」ために使用できるC ++の関数ポインターと比較しています。

于 2012-07-07T14:19:14.163 に答える