问题描述
我正在C#中学习指针,如果C#中可以使用C ++风格的函数指针,那么很好奇。是的,我知道C#有自己的功能指针的等效概念(称为代理)。但是我只想知道如果使用C#中的指针可以实现同样的目的,而不使用代理。如果在C#(使用不安全选项)中使用指针是完全合法的,并且指针语义几乎类似于C / C ++,那么在我看来,也应该可以使用C / C ++风格的函数指针。请指导我这个。可能吗?如果不是,那么为什么?
请注意C#和C / C ++中指针使用的相似性,如下面的示例
$ b $在C#中使用指针(非常类似于C / C ++)* /使用System; b
命名空间UnsafeCodeApplication
{
class TestPointer
{
public unsafe static void Main()
{
int [] list = {10,100,200};
fixed(int * ptr = list)
/ *让我们在指针* /
中有数组地址(int i = 0; i {
Console.WriteLine(Address of list [{0}] = {1},i,(int)(ptr + i));
Console.WriteLine(List of list [{0}] = {1},i,*(ptr + i));
}
Console.ReadKey();
}
}
}
其他答案说明C#对于函数指针没有任何内置的支持,即使在不安全的模式下也是正确的。
有趣的是考虑实现此功能将需要什么。因为它发生,我 在未发行的C#的原型版本中实现了这一功能。周围。可能2011年。
我们决定对原型进行审查,认为语法不够愉快,使用情况不足以证明该功能正在进行中。
首先,功能与代表有什么优势?代表是类型安全的,很好地捕获对绑定到其接收器的函数的引用的语义。然而,在一些系统场景中,首先将原始指针用于内存的情况相同 - 代理人的重量太重了。它们是垃圾收集,它们增加收集压力,它们是一个大的对象,与指针的大小相比,它们在每次调用时都有成本,等等。或者,您可能正在构建自己的自定义布局vtables来与一些特别令人讨厌的非托管代码进行交互操作,并且您希望调用刚刚放在vtable中的函数指针。等等。
CLR具有必要的指令: calli
,一种指针间接调用。但是C#中没有任何语法结构,这将导致C#编译器发出这个指令。
那么问题是什么?只是添加一些导致这个被排除的语法,对吧?
问题是:什么语法?为了确保CLR的物理堆栈保持正确对齐,编译器必须知道通过指针调用的方法的签名。当然,我们已经有了一种机制来表示一个方法的签名:这就是所谓的委托,而且我们已经拒绝使用这样一个事情。此外,请记住,我们在这里谈论实际上要被操纵的物理堆栈,而不是CLR的抽象评估堆栈。调用函数的签名必须包括例如函数指针是cdecl还是syscall。
我们挣扎了一段时间才想出一些没有看起来很可怕,无论以哪种方式我们尝试,它看起来更可怕。我实际上不记得我们最终实现了原型的符号;我想我可能已经阻止了。我可能在我的笔记中有一个地方,但不幸的是我现在没有时间看。
这个功能还是每隔一段时间提出来的。目前C#团队的管理有一个在低级应用程序中使用托管语言的历史,所以现在可能是一个很好的时机,如果你有一个强大的用例再次推出。
I am learning pointers in C# and was curious if one can use C++ style function pointers in C#. Yes, I know C# has its own equivalent concept for Function Pointers(called as delegates). But I just want to know if the same can be achieved using pointers in C#, without using delegates.
If using pointers is completely legal in C#(using unsafe option) and pointer semantics is almost similar to C/C++ then in my opinion one should also be able to use C/C++ style function pointers as well. Please guide me on this. Is it possible? If yes how?, If not then why?
Please notice the similarity of pointer usage in C# and C/C++ as depicted in below example
/* Using pointers in C# (Very similar to C/C++) */
using System;
namespace UnsafeCodeApplication
{
class TestPointer
{
public unsafe static void Main()
{
int[] list = {10, 100, 200};
fixed(int *ptr = list)
/* let us have array address in pointer */
for ( int i = 0; i < 3; i++)
{
Console.WriteLine("Address of list[{0}]={1}",i,(int)(ptr + i));
Console.WriteLine("Value of list[{0}]={1}", i, *(ptr + i));
}
Console.ReadKey();
}
}
}
The other answers which note that C# has no built-in support whatsoever for function pointers, even in unsafe mode, are correct.
It is interesting to consider what it would take to implement this feature. As it happens, I have implemented this feature in an unreleased prototype version of C# back in... 2010? Around then. Maybe 2011.
We decided upon review of the prototype that the syntax was insufficiently pleasant and the usage cases were insufficiently compelling to justify going forward with the feature.
First off, what is the compelling benefit of the feature over delegates? Delegates are typesafe and nicely capture the semantics of a reference to a function bound to its receiver. However, in some "systems" scenarios -- the same scenarios in which you would be using raw pointers to memory in the first place -- delegates are simply too heavyweight. They are garbage collected, they increase collection pressure, they're a large object compared to the size of a pointer, they have costs on every invocation, and so on. Or, you might be constructing your own custom layout vtables to interoperate with some particularly nasty bit of unmanaged code, and you wish to invoke a function pointer that you've just put down in your vtable. And so on.
The CLR has the necessary instruction:calli
, a pointer-indirected call. But there is no syntactic construct in C# whatsoever that will cause the C# compiler to emit this instruction.
So what's the problem? Just add some syntax that causes this to be emitted, right?
The problem is: what syntax? In order to ensure that the CLR's physical stack remains aligned correctly, the compiler must know the signature of the method being invoked via the pointer. Of course we already have a mechanism for saying what the signature of a method is: that's called a delegate, and we've already rejected the use of such a thing. Moreover, remember, we are talking here about the physical stack that is actually going to be manipulated, not the CLR's abstract evaluation stack. The signature of the function invoked must include things like whether the function pointer is cdecl or syscall, for instance.
We struggled for some time to come up with something that did not look hideous, and whichever way we tried, it looked more hideous. I actually do not recall what notation we ended up implementing for the prototype; I think I may have blocked it out. I might have it in my notes somewhere, but unfortunately I do not have time to look right now.
The feature is still brought up every now and again. The current management of the C# team has a history with using managed languages in low-level applications, so now might be a good time to pitch it again if you have a strong use case.
这篇关于如何在C#中实现C ++风格的函数指针,而不使用代理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!