【问题标题】:How to implement using LINQ or lambdas? [closed]如何使用 LINQ 或 lambdas 实现? [关闭]
【发布时间】:2017-08-16 15:21:54
【问题描述】:

我很好奇是否可以使用 LINQ 语句或 lambda 来实现以下内容。我对两者都很陌生,所以我不太确定它是如何编码的。目的是拥有一个 Func 委托,我可以向其添加多个回调,并将它们全部评估为所有返回值的布尔 AND 表达式。一个优选的解决方案将允许单个错误来短路其余的评估。我以蛮力的方式实现了这一点,代码和输出如下所示:

using System;
using System.Diagnostics;
using System.Windows.Forms;

namespace TestHarness
{
    public partial class Form1 : Form
    {
        Func<bool, bool, bool, bool> validPosition;

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            validPosition += Func1;
            validPosition += Func2;
            validPosition += Func3;

            Delegate[] delegates = validPosition.GetInvocationList();

            bool composite = true;
            int i = 0;

            foreach (Func<bool, bool, bool, bool> d in delegates)
            {
                composite = composite & d(false, true, true);
                if (!composite)
                    break;
                ++i;
            }
            Debug.WriteLine("Result: " + composite + "\tIterations: " + i);

            composite = true;
            i = 0;
            foreach (Func<bool, bool, bool, bool> d in delegates)
            {
                composite = composite & d(true, false, true);
                if (!composite)
                    break;
                ++i;
            }
            Debug.WriteLine("Result: " + composite + "\tIterations: " + i);

            composite = true;
            i = 0;
            foreach (Func<bool, bool, bool, bool> d in delegates)
            {
                composite = composite & d(true, true, false);
                if (!composite)
                    break;
                ++i;
            }
            Debug.WriteLine("Result: " + composite + "\tIterations: " + i);

            composite = true;
            i = 0;
            foreach (Func<bool, bool, bool, bool> d in delegates)
            {
                composite = composite & d(true, true, true);
                if (!composite)
                    break;
                ++i;
            }
            Debug.WriteLine("Result: " + composite + "\tIterations: " + i);
        }

        bool Func1(bool a, bool b, bool c)
        {
            return a;
        }
        bool Func2(bool a, bool b, bool c)
        {
            return b;
        }
        bool Func3(bool a, bool b, bool c)
        {
            return c;
        }
    }
}

Output:

Result: False   Iterations: 0
Result: False   Iterations: 1
Result: False   Iterations: 2
Result: True    Iterations: 3

感谢您的任何建议。

【问题讨论】:

  • 虽然这里是主题;你可以考虑去 CodeReview.SE 解决工作代码问题
  • 我没有看到任何蛮力。你真的需要这些计数吗?
  • 如果您将其简化为简单的谓词Func&lt;T,bool&gt;,您可以通过&amp;&amp; 运算符将它们链接起来,并受益于它的短路特性。但我不确定你想要达到什么目的。更大的图景是什么?
  • “有一个 Func 委托,我可以向其中添加多个回调”——在我看来,这个要求迫使您采用 GetInvocationList() 方法。请解释要求,或者您为什么认为即使有该要求,也可能有替代解决方案。坦率地说,到目前为止,这个问题要么“不清楚”,要么“太宽泛”。
  • 这样做的最终目的是在游戏中具有不同类型的可安装对象,这些对象具有 1 到 n 个标准来确定是否可以将其放置在特定图块上。该类使用组合而不是继承,“Wall”类型的对象只有一个标准 - 瓷砖是空的吗? “门”类型的可安装对象具有标准 - 瓷砖是空的吗?南北有墙,还是东、西有墙?当可安装对象被实例化时,“n”个回调将被添加到其回调 Func 委托中,该委托应按上述方式进行评估。

标签: c# linq lambda boolean expression


【解决方案1】:

我会亲自创建一个自定义扩展方法并将逻辑放入其中(很可能在您的示例中使用 foreach 来避免闭包和 lambda 开销)。但既然您对 LINQ 解决方案感兴趣,All 扩展方法正是您所需要的:

结果:

true 如果源序列的每个元素都通过了指定谓词中的测试,或者如果序列为空;否则,

短路:

一旦确定结果,就停止对源的枚举。

等效的示例 LINQ 代码:

var delegates = validPosition.GetInvocationList().Cast<Func<bool, bool, bool, bool>>();

Debug.WriteLine("Result: " + delegates.All(d => d(false, true, true)));
Debug.WriteLine("Result: " + delegates.All(d => d(true, false, true)));
Debug.WriteLine("Result: " + delegates.All(d => d(true, true, false)));
Debug.WriteLine("Result: " + delegates.All(d => d(true, true, true)));

【讨论】:

  • 太棒了!谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-06-09
  • 1970-01-01
  • 2020-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-06
相关资源
最近更新 更多