string.AsSpan 等同于 Encoding.Unicode.GetBytes 吗?

问题描述 投票:0回答:1

Encoding.Unicode.GetBytes(string)
返回字符串的 UTF-16 字节表示形式,但由于字符串在 C# 中编码为 UTF-16,是否相当于使用
MemoryMarshal.Cast<char, byte>(str.AsSpan())
获取字符串的原始字节?

看看 Encoding.Unicode.GetBytes 的实现,它看起来确实更复杂,所以我错过了什么?

.net utf-16
1个回答
0
投票

它们大部分相同,但并不完全相同。

.NET 字符串只是 UTF-16 代码点序列,无论它们是否是有效的 Unicode 字符串。特别是,这意味着未配对的代理会产生不同的行为。这个测试字符串产生不同的字节结果

あ Hello!\uDDDD
(非 ASCII 日语字符最终并没有导致差异,但我总是喜欢检查这一点):

Encoding.Unicode.GetBytes:
66, 48, 32, 0, 72, 0, 101, 0, 108, 0, 108, 0, 111, 0, 33, 0, 253, 255 
MemoryMarshal.Cast: 
66, 48, 32, 0, 72, 0, 101, 0, 108, 0, 108, 0, 111, 0, 33, 0, 221, 221

虽然 .NET 字符串可能是无效的 Unicode,但 Encoding.Unicode.GetBytes 处理有效的 Unicode,因此用 Unicode 替换字符 � 、 U+FFFD 替换了不成对的代理(它可以配置为抛出异常,但是我不认为它可以很容易地配置为模仿 MemoryMarshal.Cast 行为)。

此外,

MemoryMarshal.Cast
可能存在依赖于系统的行为。 .NET 中的
Char
被定义为 UTF-16 代码单元,但 documentation 未指定字节顺序。大端架构可能会根据端序交换每对字节(尽管从我的快速搜索来看,大端架构上的 .NET 实现很少见)。此外,虽然我在内存管理代码方面不太有经验,但根据
文档
MemoryMarshal.Cast
可能会在某些平台上失败:

仅在支持未对齐内存访问或通过其他方式对齐内存块的平台上才支持此方法。

这是未配对代理字符串的测试代码:

MemoryMarshal.Cast

	
© www.soinside.com 2019 - 2024. All rights reserved.