代码之家  ›  专栏  ›  技术社区  ›  Mark A. Donohoe

对于C,在调用诸如getWindowText之类的win32函数时,是否存在使用“string”而不是“stringbuilder”的缺点?

  •  9
  • Mark A. Donohoe  · 技术社区  · 7 年前

    考虑这两个定义 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}'");
    

    不管我是否通过 一串 ,或者 字符串拼接 . 但是,我看到的所有示例都使用 字符串拼接 变体。即使是pinvoke.net也会列出那个。

    我的猜测是“在C字符串中”的思想是不可变的,因此使用 字符串拼接 但是,由于我们深入到win32 api并直接处理内存位置,并且内存缓冲区是为所有意图和目的(pre)分配的(即为字符串保留并当前由字符串使用),根据其定义分配值的性质,该限制实际上不适用,因此 一串 工作很好。但我想知道这个假设是否是错误的。

    我不这么认为,因为如果您通过将缓冲区增加10来测试这个问题,并将初始化时使用的字符更改为“a”,然后将较大的缓冲区大小传递给getwindowtext,则返回的字符串是实际的标题,用未被覆盖的额外10个“a”右填充,显示它确实更新了内存位置。前面的字符。

    所以,如果您预先初始化字符串,您就不能这样做吗?当使用这些字符串时,是否会因为CLR假设它们是不可变的而“从您的下方移出”?这就是我想知道的。

    2 回复  |  直到 7 年前
        1
  •  1
  •   Mark A. Donohoe    7 年前

    string

    buffer.Length

    StringBuilder ToString()

        2
  •  3
  •   Mark A. Donohoe    7 年前

    // You can use either of these as they both work
    var buffer = new string('\0', windowTextLength);
    

    // assuming windowTextLength is 5
    var buffer = "\0\0\0\0\0"; 
    

    String/string StringBuilder

    GC The Managed Heap and Garbage Collection in the CLR

    1. Fixed-Length String Buffers string