C# DllImport-ANSI与Unicode

C# DllImport-ANSI与Unicode,c#,pinvoke,C#,Pinvoke,我对以下测试问题的可能答案有一些疑问: 问题:您编写以下代码段,以使用平台调用从Win32应用程序编程接口(API)调用函数 string personName = "N?el"; string msg = "Welcome" + personName + "to club"!"; bool rc = User32API.MessageBox(0, msg, personName, 0); 您需要定义一个能够最好地封送字符串数据的方法原型。您应该使用哪个代码段 // A. [DllImport

我对以下测试问题的可能答案有一些疑问:

问题:您编写以下代码段,以使用平台调用从Win32应用程序编程接口(API)调用函数

string personName = "N?el";
string msg = "Welcome" + personName + "to club"!";
bool rc = User32API.MessageBox(0, msg, personName, 0);
您需要定义一个能够最好地封送字符串数据的方法原型。您应该使用哪个代码段

// A.
[DllImport("user32", CharSet = CharSet.Ansi)]
public static extern bool MessageBox(int hWnd, string text, string caption, uint type);
}

// B.
[DllImport("user32", EntryPoint = "MessageBoxA", CharSet = CharSet.Ansi)]
public static extern bool MessageBox(int hWnd,
[MarshalAs(UnmanagedType.LPWStr)]string text,
[MarshalAs(UnmanagedType.LPWStr)]string caption, uint type);
}

// C. - Correct answer
[DllImport("user32", CharSet = CharSet.Unicode)]
public static extern bool MessageBox(int hWnd, string text, string caption, uint type);
}

// D.
[DllImport("user32", EntryPoint = "MessageBoxA", CharSet = CharSet.Unicode)]
public static extern bool MessageBox(int hWnd,
[MarshalAs(UnmanagedType.LPWStr)]string text,
[MarshalAs(UnmanagedType.LPWStr)]string caption,
uint type);
}
为什么正确答案是C?难道这就不能算是一场灾难吗?唯一的区别是它将是ANSI而不是Unicode

我知道它不能是D,因为我们选择Unicode作为字符集,然后使用ANSI函数作为入口点


为什么B不起作用?

我怀疑答案在
人名中

我认为它没有正确地粘贴到你的问题中

string personName = "N?el";
请注意
字符。我认为这表明原始字符串中有一个非ANSI字符。如果这是真的,并且您可以正确地看到这一点,那么它将表明您必须使用Unicode而不是ANSI(因此答案必须是
C


在任何情况下,Unicode都可以使用比ANSI更多的格式,因此它是一个更好的默认选择。

字符集。除非另有指示,否则ANSI
会告诉封送员以ANSI格式封送。同样地,除非另有指示,否则
CharSet.Unicode
是一条封送为UTF-16的指令

由于选项B和D确实指示相反,因此
字符集
参数被覆盖,因此选项B和D实际上是等效的。它们都不正确,因为您要求使用名为
MessageBoxA
的函数,该函数需要ANSI文本

剩下A和C。选项A调用函数的ANSI变量
MessageBoxA
,选项C调用Unicode变量
MessageBoxW
。在幕后,p/invoke封送处理程序使用
CharSet
参数的值选择适当的入口点

现在,您可以使用A或C,但区别在于,使用选项A,您将传递ANSI编码的文本。如果您传递的文本包含无法用ANSI编码的字符,则会丢失信息。这就是为什么C是首选。它将始终接收与.net调用代码中存在的文本完全相同的文本

 string personName = "N?el";
这个字符串被这个问题所问的问题弄乱了。毫无疑问,在原作中是这样的:

 string personName = "Nöel";
ö往往是个问题,它的字符代码不在ASCII字符集中,默认系统代码页可能不支持它。这是当你pinvoke ANSI版本的MessageBox,又名MessageBoxA时使用的。真正的函数是MessageBoxW,它接受utf-16编码的Unicode字符串

MessageBoxA是旧版本Windows中使用的传统函数,早在旧版本中,程序仍然使用8位字符串。它并没有完全消失,很多C和C++程序仍然倾向于用8位编码。MessagBoxA是通过将8位编码字符串转换为Unicode,然后调用MessageBoxW来实现的。如果您首先使用Unicode字符串,则With速度慢且有损

因此,对4个版本进行评级:

答:使用MessageBoxA+8位编码,有风险。
B:使用MessageBoxA+Unicode,失败。
C:使用MessageBoxW+Unicode,很好
D:使用MessageBoxA+Unicode,失败