c#中的后期评估?

c#中的后期评估?,c#,programming-languages,lazy-evaluation,C#,Programming Languages,Lazy Evaluation,我正在用c#编写一个应用程序。为了让这个应用程序正常工作,我发现自己做了一些对我选择的语言来说很不自然的事情。在经历了许多重构和改进之后,我终于意识到我试图实现的功能实际上是一种“惰性评估”(我认为)。这就是我想要的 // Criteria 1: Lazy evaluation of expressions int x = LazyEvaluated.New<int>(); int y = LazyEvaluated.New<int>(); int z = LazyEva

我正在用c#编写一个应用程序。为了让这个应用程序正常工作,我发现自己做了一些对我选择的语言来说很不自然的事情。在经历了许多重构和改进之后,我终于意识到我试图实现的功能实际上是一种“惰性评估”(我认为)。这就是我想要的

// Criteria 1: Lazy evaluation of expressions
int x = LazyEvaluated.New<int>();
int y = LazyEvaluated.New<int>();
int z = LazyEvaluated.New<int>();

z.Assign(x + y);
Assert.ThrowsException(z.Evalutate());
x.Assign(1);
Assert.ThrowsException(z.Evalutate());
y.Assign(2);
Assert.Equals(3, z.Evaluate());
x.Assign(3);
Assert.Equals(5, z.Evaluate());

// Criteria 2: Referencing relative to parent object    
Car myCar = LazyEvaluated.New<Car>();
Engine engineInMyCar = LazyEvaluated.New<Engine>();
double displacementOfMyEngine = LazyEvaluated.New<double>();

engineInMyCar = myCar.Engine;
displacementOfMyEngine = engineInMyCar.Displacement;

Car subaru = new Car(new FlatFourEngine());
Car falcon = new Car(new InlineSixEngine());

myCar.Assign(subaru);
Assert.IsTypeOf<FlatFourEngine>(engineInMyCar.Evaluate());
Assert.IsEqual(2.0, displacementOfMyEngine.Evaluate());

myCar.Assign(falcon);
Assert.IsTypeOf<InlineSixEngine>(engineInMyCar.Evaluate());
Assert.IsEqual(4.0, displacementOfMyEngine.Evaluate());
我想要这个功能的原因主要是为了分离关注点。为了说明这一点,让我们进一步研究汽车模拟。我的汽车是由许多零件组成的;发动机、轮胎、内饰等。我的轮胎需要每两年由轮胎店更换一次。我的发动机需要每6个月由一名技工更换一次机油。内部需要每3个月由一名细节人员进行一次吸尘。如果能按照……的思路做点什么就好了

tyreShop.ReplaceTyres(myCar.Tyres, every2Years);
mechanic.ChangeOil(myCar.Engine, every6Months);
detailer.VacuumInterior(myCar.Interior, every3Months);
采取这种做法的一些原因

  • 我想设置和忘记。一旦我安排了一部分汽车进行维修,我希望它能够持续进行,而无需我提供任何进一步的信息
  • 我不想在我买新车的那一刻就给我的每个服务中心打电话通知他们。事实上,他们不需要知道我有一辆新车,直到需要保养的时候。如果他们试图维修我的车,但我的车不存在,那么他们可以抛出一个异常
  • 我希望我的每项服务都尽可能简单和集中。为什么要让轮胎店参考我的整个汽车(包括发动机、内饰等),而他们真正关心的是轮胎
  • 我不想让轮胎店给我一套新轮胎,强迫我自己将它们安装(分配)到汽车上
我没有接受过任何正式的CS教育,我唯一的编程经验就是使用c&c语言。我刚刚花了6个月的时间熟悉c#&Net。在大多数情况下,我真的很喜欢语言和早期评估。但我现在质疑的是,如果使用一种不同的语言来解决我的特定问题,并内置对惰性评估的支持,是否会更好

我的问题是,

  • 如果我重新开始,用什么语言来解决这个问题最好
  • 现有的c#平台是否支持延迟评估
  • 在c#中实现此功能的替代方案有哪些?有没有什么特别的设计模式需要我仔细阅读

  • .NET 4使用
    lazy
    内置了对延迟初始化的支持,请参见MSDN上的文档。

    听起来你真正想要的是将一项行动安排在以后重复进行。我建议委托-可能使用lambda表达式-是最合适的方法:

    scheduler.Schedule(every3Months, () => tyreShop.ReplaceTyres(myCar));
    

    这样,您的代码中唯一需要了解惰性方面的部分就是调度器本身。所有代码的其余部分都可以假设,当您调用一个方法时,您希望立即执行该操作,这是一个更为惯用的C#。

    +1对于一个格式非常好的问题。关于手头的事情,我认为“商店”可以也应该提到整辆车:如果你需要换轮胎,你把车带到商店,你通常不会自己取下轮胎去换:)而且,如果你的“商店”处理的是
    汽车
    参考,您可以组成一个
    Shop
    超类,让他们从中继承,该超类可以处理常见任务(从而允许您进行干燥)。更不用说(为了更接近您的示例),这允许您进行有趣的行为,例如,商店在您的
    汽车周围通过来执行各种任务。@alex:谢谢您的回复。说得好——把我的整辆车交给轮胎店更换轮胎似乎并不不合理。但是如果我有一个更深层的对象层次结构,如下所示……
    tyreShop.replacetriers(myFamily.layer.Car,every2年)
    。把我的家人介绍给TyreShop绝对是不对的。但是如果我发现她和卖牛奶的人偷情的话,我可能会这样做。在这种情况下,提供给轮胎店的汽车实例需要更新,以反映我新妻子的汽车。我注意到,为了回应人们的建议,我在某种程度上扭曲了我的示例,对此我深表歉意。我发现用一个简单的例子来描述我所在领域的真正复杂性有点困难。我会等待一段时间,然后接受最能解决我提出的实际问题/例子的回答。我已经读过这方面的内容,但我不认为这完全是我想要的。惰性类型似乎只支持惰性初始化。我希望it支持更一般的惰性评估。如果我使用Lazy.Value.Engine,它提供给我的引擎将不会是懒惰的。另外,我希望我的惰性对象具有与分配给它的对象相同的类型(而不是惰性对象)。对于我在问题中发布的简单示例,这是一个很好的解决方案。如果只有一个调度器,那么我可以让调度器在将依赖项传递给服务之前解析所有依赖项。但假设现在我有一家车身修理店,在一次汽车爆炸后修理我的汽车;车身修理厂。固定底盘(我的车,我的车。事故后)。在我的实际应用程序中,我有许多这样的触发器(一些基于时间,一些基于事件),它们可以导致服务执行。如果我换了我的车,我不想为了给它我的车的新实例而不得不手动跟踪每一个调度器/触发器。@knick:我怀疑在这一点上,与我想象的你的真实需求相比,这个类比是适当的扭曲,我们不能明智地提出具体的建议。例如,您可以使用
    bodyShop.FixChassis(me.MyCar)
    来代替,在执行委托时,它将始终获取您的“当前汽车”。。。但我不知道这是否真的符合你的项目。今天我了解到
    scheduler.Schedule(every3Months, () => tyreShop.ReplaceTyres(myCar));