C # рдореЗрдВ рдПрдХ рдФрд░ рдкреИрдЯрд░реНрди рдорд┐рд▓рд╛рди

рд╣рд╛рд▓ рд╣реА рдореЗрдВ, рд╕реА # рднрд╛рд╖рд╛ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ, рдореБрдЭреЗ рдПрдХ рдкреИрдЯрд░реНрди рдорд┐рд▓рд╛рди рддрдВрддреНрд░ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╕реЗ рдЕрдзрд┐рдХ рддреАрд╡реНрд░ рд╣реЛ рдЧрдпрд╛, рдЬреЛ рдХрдИ рдЖрдзреБрдирд┐рдХ рдмрд╣реБ-рдкреНрд░рддрд┐рдорд╛рди рднрд╛рд╖рд╛рдУрдВ (рдПрдл #, рд╕реНрдХрд╛рд▓рд╛, рдЖрджрд┐) рдореЗрдВ рдореМрдЬреВрдж рд╣реИ, рд▓реЗрдХрд┐рди рд╕реА # рдореЗрдВ рдЙрдкрд▓рдмреНрдз рдирд╣реАрдВ рд╣реИред рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рдЖрдзреЗ рдШрдВрдЯреЗ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж рдкрд╛рдпрд╛ рдЧрдпрд╛ ( рдЙрджрд╛рд╣рд░рдг ) рдиреЗ рдзрд╛рд░рд╛рдкреНрд░рд╡рд╛рд╣ рдЗрдВрдЯрд░рдлреЗрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдореИрдЪ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐рдпреЛрдВ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░рдиреЗ рдХрд╛ рд╕реБрдЭрд╛рд╡ рджрд┐рдпрд╛, рдЬреЛ, рдореЗрд░реА рд░рд╛рдп рдореЗрдВ, рдмрд▓реНрдХрд┐ рдмреЛрдЭрд┐рд▓ рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рд╣реИред рджреВрд╕рд░рд╛ рджреЛрд╖, рдЬреЛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдЙрдкрдпреЛрдЧ рдХреЗ рд▓рд┐рдП рдЕрдзрд┐рдХ рдЖрд╡рд╢реНрдпрдХ рд╣реИ, рдРрд╕реЗ рдорд╛рдЪрд┐рд╕ рдореЗрдВ "рд╣реБрдб рдХреЗ рдиреАрдЪреЗ" рд╣реЛрдиреЗ рд╡рд╛рд▓реЗ рд▓реВрдк рдореЗрдВ рдПрдВрдмреЗрдбреЗрдЯрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдУрд╡рд░рд╣реЗрдб рд╣реИред рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рдореИрдВрдиреЗ рдирдореВрдиреЗ рдХреЗ рд╕рд╛рде рддреБрд▓рдирд╛ рдХреЗ рдЕрдкрдиреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд┐рдпрд╛, рджреЛ рдмреБрдирд┐рдпрд╛рджреА рд╕рд┐рджреНрдзрд╛рдВрддреЛрдВ рджреНрд╡рд╛рд░рд╛ рдирд┐рд░реНрджреЗрд╢рд┐рдд:





рдЬреЛ рд╣реБрдЖ - рдЙрд╕рдХреЗ рд▓рд┐рдП рдореИрдВ рдХрдЯ рдорд╛рдВрдЧрддрд╛ рд╣реВрдВ





рджрд┐рдЦрд╛рд╡рдЯ



рдкреНрд░рд╛рд░рдВрдн рдореЗрдВ, рдореИрдВ рдореИрдЪ рдХреЗ рдбрд┐рдЬрд╛рдЗрди рдХреЛ "рд╡рд╛рд╕реНрддрд╡рд┐рдХ" рдХреА рддрд░рд╣ рдмрдирд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛, рдЬреЛ рдХрд┐ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ рд╢реНрд░реГрдВрдЦрд▓рд╛ рдХреЙрд▓ рд╕реЗ рдмрдЪрддрд╛ рдерд╛ред рдпрд╣ "рдкреНрд░рд┐рдбреАрдХреЗрдЯ - рдлрд╝рдВрдХреНрд╢рди" рдЬреЛрдбрд╝реЗ рдХреА рдПрдХ рд╕реВрдЪреА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рд╢реЙрд░реНрдЯрд╣реИрдВрдб рд╕реВрдЪреА рдЖрд░рдВрднреАрдХрд░рдг рд╕рд┐рдВрдЯреИрдХреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдорд┐рд▓рд╛рдирдХрд░реНрддрд╛ рд╡рд░реНрдЧ IEnumerable рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдПрдХ рдРрдб рд╡рд┐рдзрд┐ рднреА рд╣реИред рдЙрдкрдпреЛрдЧ рдореЗрдВ рдЖрд╕рд╛рдиреА рдХреЗ рд▓рд┐рдП (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЪрдпрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП), рдХрдХреНрд╖рд╛ рдореЗрдВ рдлрдВрдХ <> рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдХрд╛рд╕реНрдЯ рд╡рд┐рдзрд┐ рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рдерд╛



рдпрд╣рд╛рдБ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп рдпрд╣ рдХреИрд╕рд╛ рджрд┐рдЦрддрд╛ рд╣реИ:

Func<string, int> match = new Matcher<string, int> { {s => string.IsNullOrEmpty(s), s => 0}, {s => true, s => s.Length} }; int len1 = match(null); // 0 int len2 = match("abc"); // 3
      
      







рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди



рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рдЦреЛрдЬ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рдкрд╣рд▓рд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди "рдЕрдиреБрднрд╡рд╣реАрди" рдерд╛, рдФрд░ рдЬреИрд╕реЗ рдкрд╛рдпрд╛ рдЧрдпрд╛, рдореИрдЪ рдХреЗ рд▓рд┐рдП рдкрд╛рд░рд┐рдд рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд╕рд╛рде рдмрджрд▓реЗ рдореЗрдВ рднрд╡рд┐рд╖реНрдпрд╡рд╛рдгреА рдХреАред рдЬрдм рдХреЛрдб рдкрд╣рд▓реЗ рдмрд┐рдВрджреБ рдкрд░ рд╕рдВрддреБрд╖реНрдЯ рд╣реЛрдирд╛ рд╢реБрд░реВ рд╣реБрдЖ (рдмрд╛рд╣рд░реА рд░реВрдк рд╕реЗ рднрд╛рд░реА рдирд╣реАрдВ), рддреЛ рдореИрдВрдиреЗ рдПрдХреНрд╕рдкреЛрд░реНрдЯрд░ <рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдорд┐рд▓рд╛рдирдХрд░реНрддрд╛ рдХреЛ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦрд╛ред



 public class ExprMatcher<TIn, TOut> : IEnumerable<Pair<Expression<Predicate<TIn>>, Expression<Func<TIn, TOut>>>> { private Func<TIn, TOut> _matcher; private Func<TIn, TOut> Matcher { get { return _matcher ?? (_matcher = CompileMatcher()); } } private readonly List<Pair<Expression<Predicate<TIn>>, Expression<Func<TIn, TOut>>>> _caseList = new List<Pair<Expression<Predicate<TIn>>, Expression<Func<TIn, TOut>>>>(); public void Add(Expression<Predicate<TIn>> predicate, Expression<Func<TIn, TOut>> function) { _caseList.Add(new Pair<Expression<Predicate<TIn>>, Expression<Func<TIn, TOut>>>(predicate, function)); } private Func<TIn, TOut> CompileMatcher() { var reverted = Enumerable.Reverse(_caseList).ToList(); var arg = Expression.Parameter(typeof(TIn)); var retVal = Expression.Label(typeof(TOut)); var matcher = Expression.Block( Expression.Throw(Expression.Constant(new MatchException("Provided value was not matched with any case"))), Expression.Label(retVal, Expression.Constant(default(TOut))) ); foreach (var pair in reverted) { retVal = Expression.Label(typeof(TOut)); var condition = Expression.Invoke(pair.First, arg); var action = Expression.Return(retVal, Expression.Invoke(pair.Second, arg)); matcher = Expression.Block( Expression.IfThenElse(condition, action, Expression.Return(retVal, matcher)), Expression.Label(retVal, Expression.Constant(default(TOut))) ); } return Expression.Lambda<Func<TIn, TOut>>(matcher, arg).Compile(); } public TOut Match(TIn value) { return Matcher(value); } public static implicit operator Func<TIn, TOut>(ExprMatcher<TIn, TOut> matcher) { return matcher.Match; } public IEnumerator<Pair<Expression<Predicate<TIn>>, Expression<Func<TIn, TOut>>>> GetEnumerator() { return _caseList.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } }
      
      







рдорд╛рдЪрд┐рд╕ () рдореЗрдердб рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдпрд╛ рдлрдВрдХ рдХреЛ рдХрд╛рд╕реНрдЯрд┐рдВрдЧ рдХрд░рддреЗ рд╕рдордп, рдПрдХ рдЬрдВрдЬреАрд░ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдмрдирд╛рдИ рдЬрд╛рддреА рд╣реИ рдЬреЛ рдореИрдЪрдПрдХреНрд╕реИрд╕реЗрдкреНрд╢рди рдХреЛ рдлреЗрдВрдХрддреА рд╣реИ рдпрджрд┐ рддрд░реНрдХ рдХрд┐рд╕реА рднреА рд╡рд┐рдзреЗрдп рдХреЛ рд╕рдВрддреБрд╖реНрдЯ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред рдирддреАрдЬрддрди, рд╣рдо рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рд╕рдВрдХрд▓рди рд╕рдордп рдХреЗ рд░реВрдк рдореЗрдВ рдХреЗрд╡рд▓ рдПрдХ рдУрд╡рд░рд╣реЗрдб рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВред



рдмреАрдЬрдЧрдгрд┐рддреАрдп рдкреНрд░рдХрд╛рд░



рдореЗрд░реЗ рд▓рд┐рдП C # рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рдФрд░ рдиреБрдХрд╕рд╛рди рдЗрд╕рдореЗрдВ рдпреВрдирд┐рдпрди рдкреНрд░рдХрд╛рд░реЛрдВ рдХреА рдХрдореА рдереАред рдореИрдВ рдЙрдиреНрд╣реЗрдВ рдЬреЛрдбрд╝рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛, рд▓реЗрдХрд┐рди рд╕рд╛рде рд╣реА рдЙрдирдХрд╛ рдЙрдкрдпреЛрдЧ рдпрдерд╛рд╕рдВрднрд╡ рд╕реБрд░рдХреНрд╖рд┐рдд (рдПрдирдкреАрдИ рдХреЗ рд▓рд┐рдП) рдХрд░ рд░рд╣рд╛ рдерд╛ред

рд╢реБрд░реБрдЖрдд рдХреЗ рд▓рд┐рдП, рджреЛ рдкреНрд░рдХрд╛рд░реЛрдВ рдХрд╛ рд╕рдВрдпреЛрдЬрди рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛:

 public sealed class Union<T1, T2> { public object Value { get; private set; } public T1 Value1 { get; private set; } public T2 Value2 { get; private set; } public Union(T1 value) { Value1 = value; Value = value; } public Union(T2 value) { Value2 = value; Value = value; } public static explicit operator T1(Union<T1, T2> value) { return value.Value1; } public static explicit operator T2(Union<T1, T2> value) { return value.Value2; } public static implicit operator Union<T1, T2>(T1 value) { return new Union<T1, T2>(value); } public static implicit operator Union<T1, T2>(T2 value) { return new Union<T1, T2>(value); } }
      
      





рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХреЛ рджрд┐рдП рдЧрдП рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рдпрд╛ рддреЛ Value1 рдпрд╛ Value2 рдХреЛ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рдЖрд░рдВрднреАрдХреГрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдореВрд▓реНрдп рдХреЛ рднреА рдЖрд░рдВрднреАрдХреГрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣ рдЖрдкрдХреЛ рдЗрд╕рдХреА рдорджрдж рд╕реЗ рд╡рд┐рдзреЗрдп рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреЗ рдХреА рддреБрд▓рдирд╛ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдЗрд╕ рдмрд╛рдд рдХреА рдЪрд┐рдВрддрд╛ рдХрд┐рдП рдмрд┐рдирд╛ рдХрд┐ рдореВрд▓реНрдп T1 рдФрд░ T2 рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдХрд┐рд╕реА рдЕрдиреНрдп рдкреНрд░рдХрд╛рд░ рдкрд░ рд▓реЗ рдЬрд╛рдПрдЧрд╛ред T4 рдЯреЗрдореНрдкрд▓реЗрдЯ рдЗрдВрдЬрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ, 17 рдкреНрд░рдХрд╛рд░ рддрдХ рдХреЗ рдпреВрдирд┐рдпрди рдЕрдзрд┐рднрд╛рд░ рдЙрддреНрдкрдиреНрди рдХрд┐рдП рдЧрдП рдереЗред

рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдорд┐рд▓рд╛рдирдХрд░реНрддрд╛рдУрдВ рдХреЗ рдкреНрд░рд╛рд░рдВрднрд┐рдХрдХрд░рдг рдХреЛ рдЖрд╕рд╛рди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдЪрд░ рдФрд░ рдПрдХреНрд╕рдкреНрд░реИрдорд░ рдХреЗ рд╡рд╛рд░рд┐рд╕ рд▓рд┐рдЦреЗ рдЧрдП:

 public class ExprMatcher<T1, T2, T3> : ExprMatcher<T1, Union<T2, T3>> {}
      
      







рддрд╕реНрд╡реАрд░ рдХреЛ рдкреВрд░рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдмрд▓реНрдХрд┐ рдПрдХ рддреБрдЪреНрдЫ рд╡рд┐рдХрд▓реНрдк рднреА рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рдерд╛ред



рдЖрд╢рд╛ рд╣реИ рдХрд┐ рдореЗрд░рд╛ рдорд┐рд▓рд╛рди рдХрд┐рд╕реА рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧрд╛:

Bitbucket рдкреНрд░реЛрдЬреЗрдХреНрдЯ

рдирдЧреЗрдЯ рдкреИрдХреЗрдЬ



рдЖрдкрдХрд╛ рдзреНрдпрд╛рди рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж!



All Articles