关于接受的答案的快速说明:我不同意Jeffrey的一小部分答案,即Delegate必须是一个引用类型,因此所有代表都是引用类型.(多层继承链排除值类型并不是真的;例如,所有枚举类型都System.Enum继承自System.ValueType,而继承自所有引用类型的继承System.Object,但是我认为事实是从根本上说,所有代表事实上都不仅仅是继承而是来自这里的关键实现.正如雷蒙指出,在一个评论他的答案,一旦你承诺支持多用户,有真的没有一点不使用引用类型的代表本身,因为需要一个数组的地方.DelegateMulticastDelegate
请参阅底部的更新.
如果我这样做,我一直觉得很奇怪:
Action foo = obj.Foo;
Run Code Online (Sandbox Code Playgroud)
我每次都在创建一个新 Action对象.我确信成本很低,但它涉及到内存分配以便以后进行垃圾回收.
鉴于委托本身就是不可变的,我想知道为什么它们不能成为价值类型?然后像上面那样的一行代码只会对堆栈上的内存地址进行简单的赋值*.
即使考虑匿名功能,似乎(对我而言)这也行得通.请考虑以下简单示例.
Action foo = () => { obj.Foo(); };
Run Code Online (Sandbox Code Playgroud)
在这种情况下foo确实构成了一个闭包,是的.在许多情况下,我想这确实需要一个实际的引用类型(例如当局部变量被关闭并在闭包内被修改时).但在某些情况下,它不应该.例如,在上面的例子中,似乎支持闭包的类型看起来像这样: 我收回了我对此的原始观点.下面确实需要一个引用类型(或:它并不需要是的,但如果它是一个struct只是要它来获得反正盒装).所以,忽略下面的代码示例.我留下它只是为了提供具体提及它的答案的背景.
struct CompilerGenerated
{
Obj obj;
public CompilerGenerated(Obj obj)
{
this.obj = obj;
}
public void CallFoo()
{
obj.Foo();
}
}
// …Run Code Online (Sandbox Code Playgroud) 以下IL代码创建一个名为(fnptr)*(标记0x2000000 - 无效,模块mscorlib.dll)的Type实例.
ldtoken method void* ()*
call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
Run Code Online (Sandbox Code Playgroud)
这种类型的目的是什么?是否可以在C#中创建此类型实例而无需编写任何IL代码,也许可以使用反射?令牌上的Module.ResolveType抛出ArgumentOutOfRangeException.
编辑:
很明显,(fnptr)类型是IL方法指针类型的内部CLR类型表示,但是当删除最后一个时*,它只是返回IntPtr.
编辑#2:
将(fnptr)来自可在可见的功能SSCLI typestring.cpp:
Run Code Online (Sandbox Code Playgroud)// ...or function pointer else if (ty.IsFnPtrType()) { // Don't attempt to format this currently, it may trigger GC due to fixups. tnb.AddName(L"(fnptr)"); }
为什么基本的fnptr返回IntPtr可以在typehandle.cpp中看到:
Run Code Online (Sandbox Code Playgroud)OBJECTREF TypeHandle::GetManagedClassObject() const {[...]
Run Code Online (Sandbox Code Playgroud)switch(GetInternalCorElementType()) { case ELEMENT_TYPE_ARRAY: case ELEMENT_TYPE_SZARRAY: case ELEMENT_TYPE_BYREF: case ELEMENT_TYPE_PTR: return ((ParamTypeDesc*)AsTypeDesc())->GetManagedClassObject(); …
我正在尝试学习一些c#编码,并想知道函数指针的c ++概念是否包含在c#中.我看到有代表这样的事情.它们是相同的概念吗?或者他们在更基础的层面上有所不同?