デリゲートのC# ドキュメントでは、「デリゲートは、名前付きメソッドまたは匿名メソッドをカプセル化するために使用できる参照型です。デリゲートは C++ の関数ポインターに似ていますが、デリゲートはタイプセーフで安全です」
私の質問は、「安全な」デリゲートとはどういう意味ですか?
デリゲートのC# ドキュメントでは、「デリゲートは、名前付きメソッドまたは匿名メソッドをカプセル化するために使用できる参照型です。デリゲートは C++ の関数ポインターに似ていますが、デリゲートはタイプセーフで安全です」
私の質問は、「安全な」デリゲートとはどういう意味ですか?
デリゲートは、メソッドへのタイプ セーフな呼び出しを強制します。これは通常、コンパイラによって実行される静的な型チェックによって機能します。唯一の方法ではありませんが、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;
}
}
次に、このコードをいじり始めます。これは、型システムをだますためにできることのようなものです。
DynamicInvoke
呼び出しで異なる型の引数を渡すDynamicInvoke
呼び出しで異なる引数のセットを渡すこれらの試みはすべて問題なくコンパイルされます。それらのどれも実行されず、実行時例外が発生します。これがデリゲートを安全にするものです。デリゲートを使用して、スタックを不均衡にしたままにするメソッドを呼び出したり、初期化されていない、またはアクティブ化フレームの一部ではないスタックの場所にアクセスするようにターゲット メソッドを誘導したりすることはできません。マルウェアがコードをハイジャックする従来の方法。C や C++ にはそのようなランタイム チェックは存在せず、コンパイラは静的チェックのみを実行し、単純なキャストでバイパスできます。
私の質問は、デリゲートが「安全」であるとはどういう意味ですか?
デリゲートを使用して呼び出される関数には、呼び出し元のセキュリティ コンテキストが与えられます。これにより、権限の低い呼び出し元が利用できないタスクをデリゲートが実行できなくなります。デリゲートは、どこにでも実装されている関数へのポインターで初期化できます。唯一の制限は署名です。不明なソースへの関数ポインターを含むデリゲートを呼び出すときは、予期しない実装が発生する可能性があるため、呼び出し元は注意する必要があります。デリゲートを保護するには、コード アクセス セキュリティを使用します。
このコンテキストでは、安全とは、デリゲートが無効な値を保持できないことを意味すると思います。これはおそらく、タイプセーフな部分と少し重なっています。
これは、C/C++ のように、関数ポインターがメモリの無効な領域を指すようにしたり、悪意のあるコードを指すようにしたりすることができないことを意味します。
男性が言ったように、それらを「足を吹き飛ばす」ために使用できるC ++の関数ポインターと比較しています。