考虑这两个定义GetWindowText.一个使用a string作为缓冲区,另一个使用a 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}'");
无论我是通过a string还是a,它们似乎都能正常工作StringBuilder.但是,我见过的所有例子都使用了StringBuilder变体.甚至PInvoke.net也列出了那个.
我的猜测是"在C#字符串是不可变的,因此使用StringBuilder",但是因为我们正在寻找Win32 API并直接搞乱内存位置,并且该内存缓冲区用于所有意图和目的(预分配) (即保留用于字符串并且当前由字符串使用)由于其定义的值被赋予了一个值,该限制实际上并不适用,因此string工作得很好.但我想知道这个假设是否错误.
我不这么认为,因为如果你通过增加缓冲区来测试这个10,并改变你正在用'A'初始化它的字符,那么将更大的缓冲区大小传递给GetWindowText,你得到的字符串是实际的标题,右边填充了10个额外的"未被覆盖的A",表明它确实更新了早期角色的内存位置.
所以如果你预先初始化字符串,你不能这样做吗?这些字符串是否可以在使用它们时"从你身下移出",因为CLR假设它们是不可变的?这就是我想弄清楚的.