c# - 何时使用 Lazy 与 Func

标签 c#

我正在评估多个 bool 语句。它们按从上到下的顺序进行评估。一些 bool 语句的评估成本很高,所以我对它们使用了惰性。这是示例代码:

bool contactHasPermission = ContactHasPermission(id);
var contactIsInRole = new Lazy<bool>(() => IsContactInRole(contactId, roleType)); //Database call
var contactHasAtLeastXPoints = new Lazy<bool>(() => ContactHasXPoints(contactId, 100)); //database call

bool permit = contactHasPermission || contactIsInRole.Value || contactHasAtLeastXPoints.Value;

如您所见,最昂贵的语句位于惰性对象中。我可以用 Func 做同样的事情。使用其中一种的优缺点是什么?

最佳答案

LazyFunc 都不是魔法。它们唯一提供的是您可以推迟相关代码的执行。它不会使其更快,也不会使其并行,它只是稍后

使用延迟执行的主要好处是在某些情况下您可以完全避免执行。例如,如果您有这样一段代码:

a() && b() && c()

您知道只有当 a() 返回 true 时才对 b()c() 求值才有意义。 b()c() 的延迟执行永远不会发生。当您将中间结果存储在本地时(例如,为了提高可读性),您将失去此属性:

var resultOfA = a();
var resultOfB = b();
var resultOfC = c();

...

return resultOfA && resultOfB && resultOfC;

不再有任何机会延迟 b() 的执行,除非您使用像 var resultOfB = resultOfA && b(); 这样可怕的代码。但是,您也可以内联要计算的函数,而不是要计算的函数的结果

在 C# 中执行此操作的最简单方法是使用函数委托(delegate):

Func<bool> fa = () => a();
Func<bool> fb = () => b();
Func<bool> fc = () => c();

...

return fa() && fb() && fc();

但是,这意味着无论何时执行 fa,例如,您都会一次又一次地评估 a()。这可能是需要的,也可能不是。如果不需要,您将来到 Lazy 的世界。

Lazy 允许您延迟执行,但缓存执行结果,以便任何后续访问延迟对象将只使用原始延迟执行的结果,而不是评估“构造函数” "再次运行。

所以,总结一下:

  1. 您可以使用短路来避免执行 bool 表达式中的表达式。
  2. 无论上下文如何,您都可以使用 Func 来延迟执行(并可能避免执行),这样您就可以轻松编写复杂的短路模式。
  3. 您可以使用 Lazy 来延迟执行(并可能避免它),同时还可以缓存结果以用于对 lazy 值的任何后续评估。这对于具有非平凡范围的长期对象特别有用。

在您的示例代码中,最好的选择可能是 1) - 当您可以使用短路时,没有必要获得函数委托(delegate)的开销。此处延迟执行的主要好处是允许您命名表达式的部分 - 这样您就可以得到例如hasPermission() && isInRole() && isSunny() 而不是难以阅读的表达式。如果您最多只使用表达式的每个部分一次,那么使用 Lazy 就没有意义了 - 它只是意味着围绕底层 Func 的额外样板。

关于c# - 何时使用 Lazy 与 Func,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37812542/

相关文章:

c# - 允许对象移动的 WPF 容器

c# 获取不规则对象边缘坐标的替代快速方法?

c# - ContractData : returning a type of 'T' from the exception handler 的通用反序列化

c# - 未连接控制台时,Console.WriteLine 是否会在 WinForms 应用程序中占用任何时间?

C# 解析无名称的Json文件

c# - dateTime 到 winform 中的短格式

c# - 通过 SharePoint Web 部件访问列表数据

c# - Visual Studio 项目平台相关引用

c# - 身份证号码验证

c# - 可以运行 2 个后台任务 - Windows Phone 8.1 通用应用程序?