Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 模式匹配案例_C#_.net_Pattern Matching_C# 7.0 - Fatal编程技术网

C# 模式匹配案例

C# 模式匹配案例,c#,.net,pattern-matching,c#-7.0,C#,.net,Pattern Matching,C# 7.0,我编写了简单的数学标记器,并尝试使用新的C#模式匹配特性 标记器非常简单: public IEnumerable<IToken> Tokenize(string input) { const char decimalSeparator = '.'; string inputWithoutSpaces = input.Replace(" ", string.Empty); var numberBuffer = new St

我编写了简单的数学标记器,并尝试使用新的C#
模式匹配
特性

标记器非常简单:

    public IEnumerable<IToken> Tokenize(string input)
    {
        const char decimalSeparator = '.';
        string inputWithoutSpaces = input.Replace(" ", string.Empty);
        var numberBuffer = new StringBuilder();
        var letterBuffer = new StringBuilder();
        foreach (char c in inputWithoutSpaces)
        {
            switch (c)
            {
                case var _ when IsTerm(c, letterBuffer):
                    if (numberBuffer.Length > 0)
                    {
                        yield return EmptyNumberBufferAsLiteral(numberBuffer);
                        yield return new Operator('*');
                    }
                    letterBuffer.Append(c);
                    break;
                case decimalSeparator:
                case var _ when IsDigit(c):
                    numberBuffer.Append(c);
                    break;
                case var _ when IsOperator(c):
                    if (numberBuffer.Length > 0)
                    {
                        yield return EmptyNumberBufferAsLiteral(numberBuffer);
                    }
                    if (letterBuffer.Length > 0)
                    {
                        yield return EmptyLetterBufferAsTerm(letterBuffer);
                    }
                    yield return new Operator(c);
                    break;
            }
        }
        if (numberBuffer.Length > 0)
        {
            yield return EmptyNumberBufferAsLiteral(numberBuffer);
        }
        if (letterBuffer.Length > 0)
        {
            yield return EmptyLetterBufferAsTerm(letterBuffer);
        }
    }
public IEnumerable标记化(字符串输入)
{
常量字符小数分隔符=';
字符串inputWithoutSpaces=input.Replace(“,string.Empty);
var numberBuffer=新的StringBuilder();
var lettbuffer=新的StringBuilder();
foreach(inputWithoutSpaces中的字符c)
{
开关(c)
{
当IsTerm(c,字母缓冲区)时的情况变量:
如果(numberBuffer.Length>0)
{
返回空numberbufferasliteral(numberBuffer);
返回新运算符('*');
}
字母缓冲区。附加(c);
打破
大小写小数分隔符:
当为数字(c)时的情况变量:
编号buffer.Append(c);
打破
等参比器(c)时的情况变量:
如果(numberBuffer.Length>0)
{
返回空numberbufferasliteral(numberBuffer);
}
如果(letterBuffer.Length>0)
{
收益返回EmptyLetterBufferAsTerm(lettbuffer);
}
返回新运算符(c);
打破
}
}
如果(numberBuffer.Length>0)
{
返回空numberbufferasliteral(numberBuffer);
}
如果(letterBuffer.Length>0)
{
收益返回EmptyLetterBufferAsTerm(lettbuffer);
}
}
我使用的是
case-var
,因为我想在不使用
if-else-if
链的情况下按条件进行匹配,但在不指定
var-variableName
的情况下,我无法写入
case-when

有没有什么特别的方法来做这样的手术?或者这是做这些事情的推荐方法?

有一种“奇特”的方法来做这样的模式匹配,使用通常称为活动模式的方法。虽然C#还不支持活动模式,但是

因此,使用活动模式,您的代码将最终看起来像:

switch (c)
{
    case Term(letterBuffer):
        ...
        break;
    case decimalSeparator:
    case Digit():
        ...
        break;
    case Operator():
        ...
        break;
}
如果您希望在未来版本的C#中看到此功能,请参阅


与此同时,你只能在坚持别人所说的“如果”
if
语句,或者像你这样使用when-guard语句之间做出有限的选择。你选择哪一种只是偏好风格的问题。

你有点滥用模式匹配来绕过在switch语句中使用常量的要求,因此没有真正的方法来绕过它。此外,我认为您的逻辑可能与if/else语句更适合/读得更好。@DavidG相反,它看起来像是活动模式,这使得标记化器和解析器的实现更容易。C#7中的模式匹配忽略了几个重要特性。活动模式就是其中之一。我会更优先考虑彻底匹配though@PanagiotisKanavos是的,但我说的是现在可用的语言。我敢肯定,我们将来会看到更多的模式匹配内容进入C#(我想主要是因为F#),我宁愿先实现彻底的匹配,以防止“遗漏”案例。@PanagiotisKanavos完全同意。不幸的是,我认为我们将看到适当的模式匹配被推回,取而代之的是一堆其他与OO相关的特性。因此Op的伪活动模式将是一段时间内的做法。