Delegate(Object,String)
委托(类型,字符串)
Delegate构造函数具有两个参数,第一个保存方法所属的对象的引用/类型,第二个保存指向方法的指针。
当我们直接拥有方法的地址时,为什么需要引用/对象类型?有什么用?
答案 0 :(得分:2)
我只能对此进行推测。如您所说,参数是用来指定目标(类型或实例)和方法名称的。 .NET 4.7.2上的源代码是这样的:
此构造函数实际上无非是初始化委托实例。它未使用:
代表是编译器生成的类型。我不知道使用IL自定义委托的程度。看起来这些构造函数是针对根本不需要的高级场景的,或者是完全违反责任原则的。委托类与接受方法名称和对类型进行反射无关。有较干净的现有API,用于通过反射创建委托。无需使用IL编写自定义派生类型。
.NET框架从早期开始就有一些过时的东西。总而言之,.NET Framework的简洁程度令我惊讶。在这里找到一些设计错误,并且没有不好的代码基础的迹象。
答案 1 :(得分:0)
Delegate构造函数具有两个参数,第一个保存方法所属的对象的引用/类型,第二个保存方法的指针。
请更好地看一下签名:第二个参数是string
。基本想法可能是这两个构造函数的工作方式与Type.GetMethod(string)
类似,因此请在给定名称的类型内找到一个方法,但在此之上,构造函数会将其绑定到新创建的委托。请注意,该构造函数是protected
,因此您需要派生的Delegate
类型来调用此构造函数,并且可以从派生的委托类型中推定该方法的参数类型。
所以
public delegate void MyDelegate(int n);
然后您便可以:
var obj = new List<int>();
// an instance void Add(int) method is searched in the obj.GetType() type
// and bound to the del delegate
MyDelegate del = new MyDelegate(obj, "Add");
del(1); // obj.Add(1);
此功能尚未实现。您可以使用:
MyDelegate del = (MyDelegate)Delegate.CreateDelegate(typeof(MyDelegate), obj, "Add", true);
del(1); // obj.Add(1);
但是CreateDelegate()
不使用您询问的构造函数。
关于委托和方法的(本机)指针:实际上,当您创建引用方法的新委托(技术上是“方法组”)时,将使用该方法的本机指针。可以在以下example on sharplab中看到:
public delegate void TestDelegate();
public TestDelegate BuildInstanceMethodDelegate()
{
TestDelegate test = InstanceMethod;
return test;
}
public TestDelegate BuildStaticMethodDelegate()
{
TestDelegate test = StaticMethod;
return test;
}
用IL代码转换为:
.class public auto ansi sealed TestDelegate
extends [mscorlib]System.MulticastDelegate
{
// Methods
.method public hidebysig specialname rtspecialname
instance void .ctor (
object 'object',
native int 'method'
) runtime managed
{
} // end of method TestDelegate::.ctor
}
和
.method public hidebysig
instance class TestDelegate BuildInstanceMethodDelegate () cil managed
{
// Method begins at RVA 0x2052
// Code size 13 (0xd)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldftn instance void C::InstanceMethod()
IL_0007: newobj instance void TestDelegate::.ctor(object, native int)
.method public hidebysig
instance class TestDelegate BuildStaticMethodDelegate () cil managed
{
// Method begins at RVA 0x2060
// Code size 13 (0xd)
.maxstack 8
IL_0000: ldnull
IL_0001: ldftn void C::StaticMethod()
IL_0007: newobj instance void TestDelegate::.ctor(object, native int)
对TestDelegate::.ctor(object, native int)
的调用非常清楚,我们可以看到ldftn
IL指令,该指令将非托管指针(类型native int)推向实现特定方法的本地代码。评估堆栈。。我们甚至可以在ldftn
之前查看指令:如果委托是实例方法,则可以作为参考;如果委托静态方法,则可以是ldnull
。