Рассмотрим эти два определения для GetWindowText
. Один использует string
для буфера, другой использует StringBuilder
вместо:
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int GetWindowText(IntPtr hWnd, string lpString, int nMaxCount);
Вот как вы их называете:
var windowTextLength = GetWindowTextLength(hWnd);
// You can use either of these as they both work
var buffer = new string('\0', windowTextLength);
//var buffer = new StringBuilder(windowTextLength);
// Add 1 to windowTextLength for the trailing null character
var readSize = GetWindowText(hWnd, buffer, windowTextLength + 1);
Console.WriteLine($"The title is '{buffer}'");
Кажется, они оба работают правильно, независимо от того, передаю ли я string
или StringBuilder
. Однако все примеры, которые я видел, используют вариант StringBuilder
. Даже PInvoke.net перечисляет это.
Я думаю, что мысль звучит так: «В C # строки неизменны, поэтому используйте StringBuilder
», но, поскольку мы обращаемся к Win32 API и напрямую связываемся с местами памяти, и этот буфер памяти для всех целей и цели (предварительно) распределенные (т. е. зарезервированные и используемые в настоящее время для строки) по характеру присвоения ей значения в ее определении, это ограничение фактически не применяется, поэтому string
работает просто отлично. Но мне интересно, если это предположение неверно.
Я так не думаю, потому что если вы протестируете это, увеличив буфер, скажем, на 10, и измените символ, с которым вы инициализируете его, на «A», то передадите этот больший размер буфера в GetWindowText, строку вы получите реальный заголовок, дополненный десятью дополнительными буквами «А», которые не были перезаписаны, показывая, что он обновил место в памяти предыдущих символов.
Итак, если вы предварительно инициализировали строки, вы не можете это сделать? Могут ли эти строки когда-либо «выйти из-под вас» во время их использования, потому что CLR предполагает, что они неизменны? Вот что я пытаюсь выяснить.