将谓词作为参数传递给C#

Mem*_*der -1 c# predicate func

我最近从一家公司进行了评估,该公司有一个案例,他们希望将谓词设置为方法的输入参数。对此我几乎没有经验,我一直在自己研究。代码如下:

using System;

public interface IBird
{
    Egg Lay();
}

public class Chicken : IBird
{
    public Chicken()
    {
    }

    public void EggLay()
    {
    }

    public Egg Lay()
    {
        return new Egg();
    }
}

public class Egg
{
    public Egg(Func<IBird> createBird)
    {
        throw new NotImplementedException("Waiting to be implemented.");
    }

    public IBird Hatch()
    {
        throw new NotImplementedException("Waiting to be implemented.");
    }
}

public class Program
{
    public static void Main(string[] args)
    {
//      var chicken1 = new Chicken();
//      var egg = chicken1.Lay();
//      var childChicken = egg.Hatch();
    }
}
Run Code Online (Sandbox Code Playgroud)

我的问题是,Egg函数的期望是什么?为什么?

我已经看过这个答案这个答案这个答案,但仍然没有任何意义。这是学术性的,但我真的很想理解。

Oli*_*bes 7

public Egg(Func<IBird> createBird)是不是一个函数,它的构造函数中的Egg类。由于Egg班级必须是Hatch鸟类,因此需要创建鸟类。Func<IBird>是委托,即代表对方法的引用的值。在这种特定情况下,它表示工厂方法。谓词可以是返回布尔值的方法或委托。通过此参数,您可以传递创建IBirds的任何方法。由于该IBird接口未指定鸟类的显式实现,因此可以Egg使用创建不同鸟类类型的不同方法进行初始化。有些需要构造函数参数,有些则不需要。

你会实现Egg这样的

public class Egg
{
    private readonly Func<IBird> _createBird;

    public Egg(Func<IBird> createBird)
    {
        _createBird = createBird; // No "()". createBird is not called, just assigned.
    }

    public IBird Hatch()
    {
        return _createBird(); // Here createBird is called, therefore the "()".
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,该Hatch方法可以通过_createBird委托的中间人来创建鸟类,而无需了解如何创建或创建哪种类型的鸟类。

您将如何制作一个鸡蛋?好吧,首先,您需要一些鸟类实现,例如:

public class BlackBird : IBird
{
    ... your implementation goes here
}
Run Code Online (Sandbox Code Playgroud)

然后,您需要一个创建并返回的方法IBird。例如:

IBird CreateBlackBird()
{
    return new BlackBird();
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以创建一个鸡蛋

var egg = new Egg(CreateBlackBird); // No "()". CreateBlackBird is not called but referenced.
IBird newBird = egg.Hatch();
Run Code Online (Sandbox Code Playgroud)

确保传递不带参数列表的方法,即不带括号,因为此时您不想调用该CreateBlackBird方法,而是要将其传递给构造函数,该函数将存储在构造函数中,_createBird以供以后使用。

Lambda表达式可动态创建一个匿名委托:

var egg = new Egg(() => new BlackBird());
Run Code Online (Sandbox Code Playgroud)

() => new BlackBird()是lambda表达式。它等效于该CreateBlackBird方法。返回类型未指定,并且从Egg构造函数的参数类型推断得出。它没有名字。方法标题中仅保留参数括号。=>替换return关键字。

在使用颜色作为构造函数参数实现了另一个bird类之后,您可以编写

var egg = new Egg(() => new ColoredBird(Color.Blue));
Run Code Online (Sandbox Code Playgroud)

也可以看看: