MSDNには以下のように記載されている。
[ MemberAccessException ]
呼び出し元には、(たとえば、メソッドがプライベート メソッドの場合に) デリゲートが表すメソッドへのアクセス権がありません。 または args にリストされているパラメータの数、順序、または型が無効です。
[ TargetException ]
デリゲートが表すメソッドがインスタンス メソッドであり、対象オブジェクトが null 参照 (Visual Basic では Nothing) です。 または デリゲートが表すメソッドが、そのメソッドをサポートしないオブジェクトまたはクラスに対して呼び出されています。
[ TargetInvocationException ]
カプセル化されたメソッドの 1 つが例外をスローします。
しかし、TargetInvocationException以外の例外&説明は、実際と全く異なる。
第一に、デリゲートが表すメソッドがプライベートメソッドだろうが、そのメソッドがプライベートメソッドを呼び出していようが、例外なんて発生しない。また、デリゲートが表すメソッドの要求するアクセス許可が呼び出し元になくて、System.Security.SecurityExceptionがスローされる場合も、MemberAccessExceptionなどスローされず、 ( SecurityExceptionをラップした ) TargetInvocationExceptionがスローされる。
第二に、argsにリストされているパラメータの数、順序、型が無効な場合でも、MemberAccessExceptionはスローされない。パラメータ の数が不正な場合はTargetParameterCountExceptionがスローされ、順序や型が向こうな場合は ArgumentExceptionがスローされる。
第三に、 「 デリゲートが表すメソッドがインスタンス メソッドであり、対象オブジェクトがnull参照 」 なんて状況はありない。 「 対象オブジェクトがnull参照 」 というのは、対象オブジェクトがGCに回収されている状況を指しているのだろうが、デリゲートが存在する限り対象オブジェクトがGCに回収されることはない。デリゲートのTargetプロパティにしっかりと対象オブジェクトの"強い"参照が保持されているから。
第四に、 「 デリゲートが表すメソッドが、そのメソッドをサポートしないオブジェクトまたはクラスに対して呼び出されています。 」 なんて状況もありえない。
まず、以下のように、デリゲートオブジェクトを普通に作成した場合、当然、メソッドとオブジェクトは正しく結びつく。
public delegate void SimpleMethod();
class Class1
{
public Class1()
{
}
public void Method1()
{
Console.WriteLine("Method1 was called.");
}
}
class Program
{
static void Main(string[] args)
{
Class1 obj = new Class1();
Delegate objMethod1 = (SimpleMethod)obj.Method1;
objMethod1.DynamicInvoke();
Console.ReadLine();
}
}
また、リフレクションを使って作成したとしても、無関係のオブジェクトと関連付けて作成することは不可能である。
public delegate void SimpleMethod();
class Class1
{
public Class1()
{
}
private void Method1()
{
Console.WriteLine("Method1 was called.");
}
}
class Program
{
static void Main(string args)
{
Assembly thisAssembly = Assembly.GetExecutingAssembly();
Type class1 = thisAssembly.GetType("Class1");
MemberInfo[] class1Member = class1.GetMember("Method1", MemberTypes.Method, BindingFlags.Instance | BindingFlags.NonPublic);
MethodInfo class1Method1Info = class1Member[0] as MethodInfo;
// 以下のコードでは、実行時に例外がスローされる。
// Delegate class1Method = Delegate.CreateDelegate(typeof(SimpleMethod), new Object(), class1Method1Info);
Delegate class1Method = Delegate.CreateDelegate(typeof(SimpleMethod), new Class1(), class1Method1Info);
class1Method.DynamicInvoke();
Console.ReadLine();
}
}
( ついでに、対象メソッドの可視性はプライベートにしてある。 )
で、結局のところ、Delegate.DynamicInvokeメソッドの例外は、正しくは以下のようになる。
[ System.ArgumentException ]
args にリストされているパラメータの順序、または型が無効である場合にスローされる。
[ System.Reflection.TargetParameterCountException ]
args にリストされているパラメータの数が、必要なパラメータ数と異なる場合にスローされる。
[ System.Reflection.TargetInvocationException ]
カプセル化されたメソッドの 1 つが例外をスローする場合にスローされる。
MSDNフォーラムにフィードバックしておきました。
http://forums.microsoft.com/MSDN-JA/ShowPost.aspx?PostID=853912&SiteID=7
2006.10.25 00:10 URL | よこけん #- [ 編集 ]
トラックバックURL↓
http://csharper.blog57.fc2.com/tb.php/37-e525ecaa