为什么C#和VB.NET以不同的方式隐式编组char *?

所以我有一个用C ++编写的函数,看起来像这样……

extern "C" __declspec(dllexport) int __stdcall SomeFunction(char *theData) { // stuff } 

…我在我当前的项目中使用它(用C#编写)。 还有其他项目使用VB编写的这个函数,如下所示:

 Public Declare Function SomeFunction Lib "MyDLL.dll" _ Alias "_SomeFunction@4" (ByVal theData As String) As Integer 

所以我尝试在C#中编写一个等价物,但是发现使用字符串类型对我来说实际上并不起作用 – 字符串会返回我传递给它的相同数据。 我尝试使用"ref string"代替通过引用传递字符串,我得到了内存访问冲突。

在做了一些挖掘之后,我发现这是C#中正确的实现:

 [DllImport("MyDLL.dll", EntryPoint = "_SomeFunction@4")] public static extern int SomeFunction(StringBuilder theData); 

现在我知道VB.NET和C#是完全不同的,但我想我总是认为字符串是字符串。 如果一种语言可以隐式地将char*送到String ,为什么不能另一种语言,需要一个完全不同的类?

(为清晰起见编辑了标题)

现在我知道VB.NET和C#是完全不同的,但我想我总是认为字符串是字符串

字符串在.net中是不可变的。 问问自己,为什么ByVal传递不可变数据类型会导致值发生变化。 对于正常函数,这不会发生,仅适用于Declare

我猜这一切都与保持与经典VB6的Declare语句的向后兼容性有关,这是通过这种方式完成的。 在我看来,这里的黑羊是VB.net代码而不是C#代码。

因为他们是不同的语言。 VB.NET可以解决很多C#无法解决的问题。 老实说,我没有看到问题。

我应该补充一下你可以简单地做一下ref char []并且它会有效。 我看到的一个问题是你的调用约定不匹配。

所以这也可能是你得到内存exception错误的原因。

由于字符串从一开始就是不可变的,我猜测VB以某种方式唤起调用以允许函数修改缓冲区。 也许内部VB实际上也传递了一个StringBuilder。

如果这是VB团队设计调用以使API调用更像VB6,我不会感到惊讶。