【问题标题】:Is there a Match like syntax for LINQLINQ 是否有类似 Match 的语法
【发布时间】:2015-10-13 17:29:34
【问题描述】:

这是我试图优雅地解决的一个案例。假设我有一个可枚举(它可能是一个相当大的可枚举,我宁愿只枚举一次)。还假设如果序列中返回的对象与操作的某些条件匹配,我想要运行特定的操作。

在函数式语言中,我可以设置在找到匹配项时执行的匹配序列。我想要在 C# 中这样的东西。尽可能使用 LINQ。

我最接近的方法是使用带有简单规则引擎的策略模式,该引擎按顺序调用每个注册的策略,直到找到匹配项。有没有更简单的方法?

我想做的是。

myEnum.Match((item)=>item.MatchesCondition, (item)=>ExecuteFunction(item))
  .Match((item)=>item.MatchesSomeOtherCondition, (item)=>ExecuteSomeOtherFunction(item));

【问题讨论】:

  • 你能展示一些示例代码吗?我对你到底要什么有点困惑。
  • 我在您输入评论时正在这样做。
  • 您是在尝试匹配枚举器中的特定项目,还是只想在找到匹配项时调用该函数?我的意思是您可以轻松地为上述逻辑创建一个扩展方法,或者只使用 foreachif/elseswitch
  • 为什么不在结果上使用Where(),然后使用foreach
  • 如果ExecuteFunction 已经为同一个对象调用过,是否应该为给定对象调用ExecuteSomeOtherFunction

标签: c# linq pattern-matching strategy-pattern


【解决方案1】:

您可以创建一个extension method Match

public static class Extensions
{
    public static IEnumerable<T> Match<T>(this IEnumerable<T> items, Func<T, bool> condition, Action<T> action)
    {
        foreach (T item in items)
        {
            if (condition(item))
            {
                action(item)
            }
            else
            {
                yield return item;
            }
        }
    }
}

这将遍历items 中的每个项目,并且:

  • 如果符合条件,执行action
  • 否则,通过iterator退货

【讨论】:

  • 我喜欢!这是完美的,它还可以防止随后的链式匹配触发。
【解决方案2】:

你可以使用现有的 LINQ 功能,如下所示:

SomeList.Where(item => item.Equals(item));

如果您不想过滤完全匹配但“包含”,则可以使用以下表达式:

SomeList.Where(item => item.Contains(item));

【讨论】:

  • 这只会过滤集合...更接近的响应将是选择语句中的开关。
【解决方案3】:

您可以创建一个包含条件和相关操作的字典,允许您继续循环遍历一系列条件,直到找到匹配项,然后调用相关操作。

void Main()
{
    var collection = new List<string> { "One", "Two" };

    var dict = new Dictionary<Func<string, bool>, Action<string>>
    {
        { ConditionOne, ActionOne },
        { ConditionTwo, ActionTwo },
    };

    Match(collection, dict);
}

public void Match<T>(IEnumerable<T> collection, 
    Dictionary<Func<T, bool>, Action<T>> matchMap)
{
    var wasMatched = false;
    foreach (var item in collection)
    {
        if (wasMatched) break;

        foreach (var pair in matchMap)
        {
            if (wasMatched) break;

            if (pair.Key(item))
            {
                pair.Value(item);
                wasMatched = true;
            }   
        }
    }
}

public bool ConditionOne<T>(T item)
{
    return false;
}

public void ActionOne<T>(T item)
{
    Console.WriteLine(item);
}

public bool ConditionTwo<T>(T item)
{
    return true;
}

public void ActionTwo<T>(T item)
{
    Console.WriteLine(item);
}

【讨论】:

    猜你喜欢
    • 2016-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-07
    • 1970-01-01
    • 1970-01-01
    • 2018-06-01
    • 1970-01-01
    相关资源
    最近更新 更多