何时使用 ReadOnlySpan<T> 与显式/重载类型

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

为了接下来的问题,假设我想将纯文本字符串转换为十六进制字符串;例如,“你好,世界!”进入“48656c6c6f2c20576f726c6421”。

这需要两个步骤:

  1. 将纯文本字符串转换为字节数组。
  2. 将字节数组转换为十六进制字符串。

例如:

string plainText = "Hello, World!";
byte[] bytes = Encoding.Default.GetBytes(plainText);
string hexadecimalString = Convert.ToHexString(bytes);

接下来,我想将此功能包装到实用函数中。在 .NET Core 2.1 之前(我很惊讶

ReadOnlySpan<T>
这么老),最灵活的方法是重载
string
char[]
;例如:

public static string ToHexString(string value, Encoding? encoding = null) =>
    ToHexString(value.ToCharArray(), encoding);
    
public static string ToHexString(char[] value, Encoding? encoding = null) =>
  Convert.ToHexString((encoding ?? Encoding.Default).GetBytes(value));

虽然这种方法相对简单,但从分配的角度来看,它并不是特别好,因为需要三个分配:

  1. ToCharArray()
    将分配一个新的
    char[]
  2. GetBytes
    将分配一个新的
    byte[]
  3. ToHexString
    将分配一个新的
    string

引入

ReadOnlySpan<T>
有可能通过减少分配数量(尽管只减少 1)来改善这一点,而且从可维护性的角度来看,它需要更少的方法重载,因为
string
char[]
可以隐式转换为
ReadOnlySpan<char>
;例如(在理想世界中):

public static string ToHexString(ReadOnlySpan<char> value, Encoding? encoding = null) =>
  Convert.ToHexString((encoding ?? Encoding.Default).GetBytes(value));

讽刺的是,虽然

ReadOnlySpan<T>
理论上应该减少分配数量,但这里的问题是
GetBytes
没有需要
ReadOnlySpan<char>
的过载,因此,实现这一点的唯一方法是重新引入分配;例如:

public static string ToHexString(ReadOnlySpan<char> value, Encoding? encoding = null) =>
  Convert.ToHexString((encoding ?? Encoding.Default).GetBytes(value.ToArray()));

目前,减少分配的唯一方法是提供方法重载,并单独实现它们;例如:

public static string ToHexString(string value, Encoding? encoding = null) =>
  Convert.ToHexString((encoding ?? Encoding.Default).GetBytes(value));
    
public static string ToHexString(char[] value, Encoding? encoding = null) =>
  Convert.ToHexString((encoding ?? Encoding.Default).GetBytes(value));

现在我们有一些方法可以减少分配,因为没有从

string
char[]
ReadOnlySpan<char>
char[]
的转换,但权衡是这会导致更高的可维护性成本,正如我现在所拥有的维护两个方法,以及为调用者提供不太灵活的 API。

所以,我的问题是,什么时候使用 ReadOnlySpan<T> 作为方法参数与使用更显式/重载的类型是正确的?权衡应该偏向于可维护性和依赖于隐式类型转换的健壮 API,还是偏向于性能?有这方面的指导吗?

附注如果您认为这值得投反对票,请礼貌地解释原因。

c# allocation
1个回答
0
投票

public static string ToHexString(ReadOnlySpan<char> value, Encoding? encoding = null) { encoding ??= Encoding.Default; int count = encoding.GetByteCount(value); Span<byte> bytes = stackalloc byte[count]; encoding.GetBytes(value, bytes); return Convert.ToHexString(bytes); }

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