Span <char>和字符串相等

时间:2018-03-15 00:08:40

标签: c#

宣布Span<T>时,我想在解析器中使用它作为我的玩具编程语言。 (实际上,我可能会存储一个Memory<char>,但这不是重点。)

但是,我已经习惯于开启字符串:

switch (myString) {
    case "function":
        return TokenType.Function;
    // etc.
}

开启一个Span<char>不会工作,并分配一个字符串进行比较以防止使用Span的目的。

切换到使用if-else语句会导致同样的问题。

那么,有没有办法有效地做到这一点? ToString()上的Span<char>是否未分配?

2 个答案:

答案 0 :(得分:3)

System.MemoryExtensions包含用于比较Span s内容的方法。

使用支持StringReadOnlySpan<char>之间的隐式转换的.NET Core,您将拥有:

ReadOnlySpan<char> myString = "function";

if (MemoryExtensions.Equals(myString, "function", StringComparison.Ordinal))
{
    return TokenType.Function;
}
else if (MemoryExtensions.Equals(myString, "...", StringComparison.Ordinal))
{
    ... 
}

我在这里显式调用MemoryExtensions.Equals是因为这样可以满足将字符串文字(例如"function")隐式转换为ReadOnlySpan<char>以进行比较的要求。如果要以面向对象的方式调用此扩展方法,则需要显式使用AsSpan

if (myString.Equals("function".AsSpan(), StringComparison.Ordinal))

如果您特别喜欢switch语句,则可以滥用模式匹配功能来偷偷进行比较,但这看起来不太可读甚至没有帮助:

ReadOnlySpan<char> myString = "function";

switch (myString)
{
    case ReadOnlySpan<char> s when MemoryExtensions.Equals(s, "function", StringComparison.Ordinal):
        return TokenType.Function;
        break;
    case ReadOnlySpan<char> s when MemoryExtensions.Equals(s, "...", StringComparison.Ordinal):
        ...
        break;
}

如果您不使用.Net Core,而不得不分别install进行System.Memory NuGet程序包,则需要在每个字符串文字后附加.AsSpan()

答案 1 :(得分:1)

调用ToString()会导致分配,因为字符串是不可变的,但是您可以考虑使用各种MemoryExtensions Class方法执行比较。因此,您可以将源代码保留在Span<char>中,并使用如下代码:

System.ReadOnlySpan<char> myString = "function test();".AsSpan();
if (myString.StartsWith("function".AsSpan()))
    Console.WriteLine("function");

这将导致为每个令牌分配中间的字符串(myString分配只是为了演示),但是您可以将令牌表初始化为令牌解析器方法外部的一次性操作。另外,您可能想研究一下Slice方法,这是在解析代码时浏览代码的有效方法。

感谢GSerg指出.NET Core可以处理从stringReadOnlySpan<char>的隐式转换,因此,如果使用AsSpan(),则可以省略function keyPressed() { if (keyIsDown(ENTER)){ player.up(); } } this.up = function() { if (this.y == 350){ if (keyIsDown(ENTER)){ this.velocity -= this.gravity*15; } else{ this.velocity += this.gravity*20000; } } } .NET Core。