我最近从一家公司进行了评估,该公司有一个案例,他们希望将谓词设置为方法的输入参数。对此我几乎没有经验,我一直在自己研究。代码如下:
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();
}
}
我的问题是Egg函数期望什么,为什么?
我已经看过this answer和this answer和this answer,但仍然没有任何意义。这是学术性的,但我真的很想了解。
答案 0 :(得分:4)
public Egg(Func<IBird> createBird)
不是一个函数,它是Egg
类的构造函数。由于Egg
类必须Hatch
个鸟,因此需要创建鸟。 Func<IBird>
是委托,即代表对方法的引用的值。在这种特定情况下,它代表一种工厂方法。谓词可以是返回布尔值的方法或委托。通过此参数,您可以传递创建IBird
的任何方法。由于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 "()".
}
}
现在,Hatch
方法可以通过_createBird
委托的中间人来创建鸟类,而无需了解如何创建鸟类。
您将如何制作一个鸡蛋?好吧,首先您需要执行一些鸟操作,例如:
public class BlackBird : IBird
{
... your implementation goes here
}
然后,您需要一个创建并返回IBird
的方法。例如:
IBird CreateBlackBird()
{
return new BlackBird();
}
然后您可以使用创建一个鸡蛋
var egg = new Egg(CreateBlackBird); // No "()". CreateBlackBird is not called but referenced.
IBird newBird = egg.Hatch();
请确保传递不带参数列表的方法(即不带括号),因为此时您不想调用CreateBlackBird
方法,您想将其传递给构造函数,并在该构造函数中进行存储在专用字段_createBird
中供以后使用。
通过使用lambda表达式,您可以即时创建匿名委托:
var egg = new Egg(() => new BlackBird());
() => new BlackBird()
是lambda表达式。
用颜色作为构造函数参数实现了另一个bird类之后,您可以编写
var egg = new Egg(() => new ColoredBird(Color.Blue));
另请参阅:
答案 1 :(得分:0)
感谢这个例子。 您可以通过修改Egg类,实现单例模式,从而使鸟只能孵化一次:
public class Egg
{
private readonly Func<IBird> _createBird;
private IBird _Bird = null;
public Egg(Func<IBird> createBird)
{
_createBird = createBird;
}
public IBird Hatch()
{
if (_Bird == null)
{
_Bird = _createBird();
}
return _Bird;
}
}
答案 2 :(得分:0)
您可以实现单例模式,以便通过如下修改Egg类来使鸟只能孵化一次。
public interface IBird
{
Egg Lay();
}
public class Egg
{
private readonly Func<IBird> _createBird;
private bool _hatched;
public Egg(Func<IBird> createBird)
{
_createBird = createBird;
}
public IBird Hatch()
{
if (_hatched)
Console.WriteLine("Egg are already hatched");
_hatched = true;
Console.WriteLine("Egg are hatched now;");
Console.ReadKey();
return _createBird();
}
}
public class Chicken : IBird
{
public Egg Lay()
{
var egg = new Egg(() => new Chicken());
return egg;
}
}
public class Program
{
public static void Main(string[] args)
{
var chicken1 = new Chicken();
var egg = chicken1.Lay();
var childChicken = egg.Hatch();
}
}