2017-05-07 23 views
5

Tôi viết trình thông báo toán học đơn giản và cố gắng sử dụng tính năng C# pattern matching mới.Trường hợp khớp mẫu khi

Tokenizer là khá đơn giản:

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); 
     } 
    } 

Tôi đang sử dụng case var _ vì tôi muốn để phù hợp với điều kiện bằng mà không sử dụng if-else if chuỗi, nhưng tôi không thể viết case when mà không chỉ định var variableName.

Có cách nào ưa thích để thực hiện thao tác như vậy không? Hoặc nó được khuyến khích cách để làm những việc này?

+1

Vâng, bạn đang loại lạm dụng mô hình phù hợp để có được xung quanh các yêu cầu của việc sử dụng hằng số trong báo cáo chuyển đổi vì vậy không có cách nào thực sự để có được xung quanh nó. Ngoài ra, tôi nghĩ rằng logic của bạn có thể phù hợp/đọc tốt hơn như nếu/else báo cáo anyway. – DavidG

+1

@DavidG ngược lại, trông giống như các mẫu hoạt động, làm cho việc triển khai mã thông báo và trình phân tích cú pháp dễ dàng hơn nhiều. Khớp mẫu trong C# 7 bỏ sót một số tính năng quan trọng. Các mẫu hoạt động là một trong số chúng. Tôi muốn ưu tiên cao hơn cho phù hợp hoàn toàn mặc dù –

+0

@PanagiotisKanavos Có, nhưng tôi đang nói về những gì có sẵn ngay bây giờ trong ngôn ngữ. Tôi khá chắc chắn chúng ta sẽ thấy nhiều thứ phù hợp với mẫu sắp tới trong C# trong tương lai (nhờ chủ yếu là F # tôi sẽ giả định) – DavidG

Trả lời

2

Có một cách "ưa thích" để thực hiện đối sánh mẫu như thế này, sử dụng những gì thường được gọi là các mẫu hoạt động. C# chưa (chưa) hỗ trợ các mẫu hoạt động, nhưng see this answer for an example of what they might look like if/when implemented.

Vì vậy, sử dụng các mẫu hoạt động, mã của bạn sẽ kết thúc tìm kiếm một cái gì đó như:

switch (c) 
{ 
    case Term(letterBuffer): 
     ... 
     break; 
    case decimalSeparator: 
    case Digit(): 
     ... 
     break; 
    case Operator(): 
     ... 
     break; 
} 

Nếu bạn muốn xem tính năng này trong một phiên bản tương lai của C#, please upvote it on the csharplang github repo.

Trong thời gian chờ đợi, khi đó bạn bị giới hạn lựa chọn giữa việc dán các câu hỏi if như những người khác đã nói hoặc sử dụng khi bảo vệ như bạn. Mà bạn đi cho thực sự chỉ là một vấn đề của phong cách ưa thích.

+0

Tôi muốn nhìn thấy kết hợp toàn diện được thực hiện trước, để ngăn chặn các trường hợp "bị nhỡ". –

+1

@PanagiotisKanavos đồng ý hoàn toàn. Thật không may tôi nghĩ rằng chúng ta sẽ thấy phù hợp với mô hình phù hợp đẩy lùi ủng hộ một loạt các tính năng liên quan đến OO khác. Vì vậy, các mẫu hoạt động giả của Op sẽ là cách để làm trong một thời gian. –

Các vấn đề liên quan