Implementing pattern matching in C#

后端 未结 5 1867
耶瑟儿~
耶瑟儿~ 2021-02-04 03:54

In Scala, you can use pattern matching to produce a result depending on the type of the input. For instance:

val title = content match {
    case blogPost: BlogP         


        
5条回答
  •  半阙折子戏
    2021-02-04 04:30

    Generic implementation I'm using, that can match against the type, condition or a value:

    public static class Match
    {
        public static PatternMatch With(T value)
        {
            return new PatternMatch(value);
        }
    
        public struct PatternMatch
        {
            private readonly T _value;
            private R _result;
    
            private bool _matched;
    
            public PatternMatch(T value)
            {
                _value = value;
                _matched = false;
                _result = default(R);
            }
    
            public PatternMatch When(Func condition, Func action)
            {
                if (!_matched && condition(_value))
                {
                    _result = action();
                    _matched = true;
                }
    
                return this;
            }
    
            public PatternMatch When(Func action)
            {
                if (!_matched && _value is C)
                {
                    _result = action((C)(object)_value);
                    _matched = true;
                }
                return this;
            }
    
    
            public PatternMatch When(C value, Func action)
            {
                if (!_matched && value.Equals(_value))
                {
                    _result = action();
                    _matched = true;
                }
                return this;
            }
    
    
            public R Result => _result;
    
            public R Default(Func action)
            {
                return !_matched ? action() : _result;
            }
        }
    }
    

    And in your case, usage would look like:

    Match.With(content)
         .When(blogPost => blogPost.Blog.Title)
         .When(blog => blog.Title)
         .Result; // or just .Default(()=> "none");
    

    Some other examples:

    var result = Match.With(new Foo() { A = 5 })
        .When(foo => foo.A)
        .When(bar => bar.B)
        .When(Convert.ToInt32)
        .Result;
    Assert.Equal(5, result);
    
    var result = Match.With(n)
        .When(x => x > 100, () => "n>100")
        .When(x => x > 10, () => "n>10")
        .Default(() => "");
    Assert.Equal("n>10", result);
    
     var result = Match.With(5)
         .When(1, () => "1")
         .When(5, () => "5")
         .Default(() => "e");
     Assert.Equal("5", result);
    

提交回复
热议问题