C# 这应该是显而易见的,但为什么失败呢?

C# 这应该是显而易见的,但为什么失败呢?,c#,.net,C#,.net,多年来一直在为.net编写代码,但我感觉自己像一个n00b。为什么下面的代码失败了 byte[] a = Guid.NewGuid().ToByteArray(); // 16 bytes in array string b = new UTF8Encoding().GetString(a); byte[] c = new UTF8Encoding().GetBytes(b); Guid d = new Guid(c); // Throws exception (32 bytes reci

多年来一直在为.net编写代码,但我感觉自己像一个n00b。为什么下面的代码失败了

byte[] a = Guid.NewGuid().ToByteArray(); // 16 bytes in array
string b = new UTF8Encoding().GetString(a);
byte[] c = new UTF8Encoding().GetBytes(b);
Guid d = new Guid(c);    // Throws exception (32 bytes recived from c)
更新

批准了CodeInChaos的回答。16字节变为32字节的原因可以从他的答案中看出。答复中还指出:

的默认构造函数 UTF8编码有错误检查 残废

当试图将字节数组编码为包含无效字节的字符串时,UTF8编码器应引发异常。为了使.net framework正常运行,应该按照以下方式编写代码

 byte[] a = Guid.NewGuid().ToByteArray();
 string b = new UTF8Encoding(false, true).GetString(a);  // Throws exception as expected
 byte[] c = new UTF8Encoding(false, true).GetBytes(b);
 Guid d = new Guid(c);

并非每个字节序列都是有效的UTF-8编码字符串

GUID几乎可以包含任何字节序列。但UTF-8作为特定规则,如果值大于127,则允许使用字节序列。Guid通常不遵循这些规则

然后,当您将损坏的字符串编码回字节数组时,您会得到一个长度超过16字节的字节数组,Guid的构造函数不接受该字节数组


关于UTF8Encoding.GetString的文档说明:

通过错误检测,无效序列会导致此方法引发ArgumentException。如果没有错误检测,将忽略无效序列,并且不会引发异常

UTF8Encoding的默认构造函数禁用了错误检查(不要问我为什么)

此构造函数创建的实例不提供Unicode字节顺序标记,并且在检测到无效编码时不会引发异常。
注意
出于安全原因,建议您的应用程序通过使用接受throwOnInvalidBytes参数的构造函数并将该参数设置为true来启用错误检测



您可能希望使用Base64编码而不是UTF-8。通过这种方式,您可以将任何有效的字节序列映射到字符串中并返回。

因为
var b
是type
string
,这意味着它是一个unicode字符串(每个字符2个字节)。在第二行中,您将从16字节数组中创建一个16个字符的字符串,但该16个字符的字符串存储在32字节中

为什么不这样做:

var d = Guid.NewGuid();

要将任意字节数据编码为字符串,应使用base-64、hex等。不能假设随机字节集构成有效的UTF*(或其他编码)字符串


那么,为什么框架在接收到无法UTF8编码的字符串时不抛出异常?不知道他们为什么会这样设计API。默认情况下,IMO默认忽略编码错误是愚蠢的。感谢您摆脱
var
。这就好像
var
的整个要点就是隐藏错误显然,字符串
b
将被传输或存储,然后在别处解码。随后直接进行解码只是因为这是演示问题的简单示例代码。