Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# NET中的代理:它们是如何构造的?_C#_.net_Delegates_Clr_.net Internals - Fatal编程技术网

C# NET中的代理:它们是如何构造的?

C# NET中的代理:它们是如何构造的?,c#,.net,delegates,clr,.net-internals,C#,.net,Delegates,Clr,.net Internals,在检查C#和.NET中的代表时,我注意到一些有趣的事实: 在C#中创建委托会创建一个派生自MulticastDelegate并带有构造函数的类: 这意味着它需要实例和指向方法的指针。然而,在C#中构造委托的语法表明它有一个构造函数 我可以将int()识别为函数实例(int*target()将是C++中的函数指针)。显然,C#编译器从函数名定义的方法组中选择正确的方法并构造委托。因此,第一个问题是,C#编译器(确切地说是Visual Studio)从何处选择此构造函数签名?我没有注意到任何特殊的属

在检查C#和.NET中的代表时,我注意到一些有趣的事实:

在C#中创建委托会创建一个派生自
MulticastDelegate
并带有构造函数的类:

这意味着它需要实例和指向方法的指针。然而,在C#中构造委托的语法表明它有一个构造函数

我可以将
int()
识别为函数实例(
int*target()
将是C++中的函数指针)。显然,C#编译器从函数名定义的方法组中选择正确的方法并构造委托。因此,第一个问题是,C#编译器(确切地说是Visual Studio)从何处选择此构造函数签名?我没有注意到任何特殊的属性或会有区别的东西。这是某种编译器/visualstudio魔法吗?如果不是,则
T(args)目标
构造是否在C#中有效?我没有设法用它编译任何东西,例如:

int()target=MyMethod

是无效的,使用
MyMetod
执行任何操作都是无效的,例如对其调用
.ToString()
(这确实有一定意义,因为从技术上讲,这是一个方法组,但我认为应该可以通过强制转换显式地选择一个方法,例如
(int())MyFunction
。那么,所有这些都是纯粹的编译器魔法吗?通过reflector查看构造可以揭示另一种语法:

Func CS$1$0000=新Func(null,(IntPtr)Foo)

这与反汇编的构造函数签名是一致的,但这不会编译

最后一个有趣的注意事项是类
Delegate
多播Delegate
还有另一组构造函数:

.method族隐藏特殊名称rtspecialname实例 void.ctor(类系统类型目标,字符串“方法”)cil管理

从实例和方法指针到类型和字符串方法名称的转换发生在何处?这是否可以用自定义委托构造函数签名中的
运行时管理的
关键字来解释,即运行时是否在此处执行其工作

编辑:好吧,我想我应该重新表述一下我想通过这个问题说的内容。基本上,我建议在委托构造中不仅要用到C#编译器/CLR魔术,还要用到一些Visual Studio魔术,因为Intellisense在建议构造函数参数时会抛出一些新语法,甚至隐藏一个of它们(例如,反射器不使用此语法和构造函数)

我想知道这个断言是否正确,函数实例语法在C#中是否有更深的含义,或者它只是Visual Studio magic部分为清晰起见实现的某种常量格式(这很有意义,因为它看起来像无效的C#)简言之,如果我正在实施Intellisense,我应该为代表们施展魔法,还是可以通过一些聪明的机制来构建建议


最终编辑:因此,流行的共识是这确实是VS magic。看到其他此类VS行为的示例(请参阅Marc Gravell的评论)让我确信情况确实如此。

您首先定义委托(Visual Studio就是这样知道目标方法的签名的):

然后,您可以像这样构造委托实例:

MyDelegate method = new MyDelegate({method name});

// If this was the method you wanted to invoke:
void MethodToInvoke()
{
    // do something
}

MyDelegate method = new MyDelegate(MethodToInvoke);
C#自动选择与委托签名匹配的方法


编辑:当VisualStudio的Intellisense向您显示
int()时target
建议,它向您显示了可以使用的C#方法的签名。C#编译器将C#表示转换为IL。IL实现看起来会有所不同,因为IL不是C风格的语言,C#编译器提供语法糖来抽象出实现细节。

第一个参数是resolv从对象引用中删除(对于静态方法,或
null
),没有魔力


但是,Re是第二个参数-它是一个非托管指针(原生int);简而言之,没有其他直接C#语法可以使用此构造函数-它使用特定的IL指令()从元数据解析函数。但是,您可以使用通过反射创建委托。您也可以使用IL emit(
DynamicMethod
等),但这并不有趣。

这只是一个猜测,所以如果我错了,请不要开枪打我,但我认为Intellisense正在从委托上定义的
Invoke
方法中获取目标方法的签名。Reflector清楚地显示
系统上的
Invoke
方法。操作
是:

[MethodImpl(0, MethodCodeType=MethodCodeType.Runtime)]
public virtual void Invoke(T obj);

这与Intellisense提供的签名建议相同。神奇之处在于,Intellisense在发现委托类型时,会查看
Invoke
方法,并建议一个构造函数,该构造函数采用与之匹配的目标。

我想他的意思是从低级角度来看。@Saulius:the
int()目标本身不是有效的C#,但它们如何在Intellisense中表示目标?。这就是问题所在-它们必须显示一些东西,所以它们只是为了清晰起见显示一些虚构的语法(仅用于代表的visual studio magic),还是说它具有更深层的含义?:)@Saulius:为了清晰起见,我假设这只是一个虚构的语法。好吧,所以方法指针不受C#支持,但“函数实例”在哪里-像语法是从哪里来的?我理解从双参数构造函数到单参数c-tor是编译器的魔法,但是visual studio从何处获得建议单参数构造函数的想法(我在其他任何地方都找不到它)?@Saulius-因为这是语言规范所要求的;它没有讨论构造函数,但它声明语法是(例如)
neweventhandler(someObject.SomeMethod);
-即使compi
delegate void MyDelegate();
MyDelegate method = new MyDelegate({method name});

// If this was the method you wanted to invoke:
void MethodToInvoke()
{
    // do something
}

MyDelegate method = new MyDelegate(MethodToInvoke);
[MethodImpl(0, MethodCodeType=MethodCodeType.Runtime)]
public virtual void Invoke(T obj);