Почему С# и VB.NET неявно маршалируют char * по-другому?

Итак, у меня есть функция, написанная на С++, которая выглядит так...

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

... и я использую его в своем текущем проекте (написанном на С#). Существуют и другие проекты, которые используют эту функцию, написанную в VB, выглядящую так:

Public Declare Function SomeFunction Lib "MyDLL.dll" _
    Alias "[email protected]" (ByVal theData As String) As Integer

Итак, я попробовал записать эквивалент в С#, но обнаружил, что использование типа строки на самом деле не работает для меня - строка вернется с теми же данными, с которыми я передал ее. Я попытался использовать "ref string" вместо этого, чтобы передать строку по ссылке, и я получил нарушение доступа к памяти.

После некоторого копания я обнаружил, что это была правильная реализация в С#:

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

Теперь я знаю, что VB.NET и С# совершенно разные, но я полагаю, что я всегда считал, что строки были строками. Если один из языков может нести марксировать char* до String, почему другой не может потребовать другого класса?

(отредактирован заголовок для ясности)

Ответ 1

Теперь я знаю, что VB.NET и С# совершенно разные, но я полагаю, что я всегда считал, что строки были строками

Строки неизменяемы в .net. Спросите себя, почему передача ByVal неизменяемого типа данных может привести к изменению значения. Этого не происходит для обычных функций, только для Declare.

Я бы предположил, что все это связано с поддержанием некоторой обратной совместимости с операторами Declare от классического VB6, которые были сделаны таким образом. На мой взгляд, черная овца здесь - код VB.net, а не код С#.

Ответ 2

Потому что они разные языки. VB.NET может многое из того, что С# не может по многим причинам. Я не вижу, чтобы проблема была честной.

Я должен добавить, что вы могли бы просто сделать ref char [], и это сработало бы. Одна из проблем, которые я вижу, заключается в том, что ваши соглашения о вызове не совпадают.

Так что, вероятно, причина, по которой вы получили ошибку исключения памяти.

Ответ 3

Так как строка является неизменной для начала, я предполагаю, что VB каким-то образом активирует вызов, позволяющий изменять буфер функцией. Возможно, внутри VB также передает StringBuilder.

Я бы не удивился, если бы это было дизайнерское предложение команды VB, чтобы сделать API более похожим на VB6.