在 C# 中变得懒惰
如果您和我一样,也一直在寻找提升应用程序运行速度的方法。在本文中,我将向您展示 .NET 框架中一个鲜为人知的类,它能够轻松实现对象的惰性创建,并且保证线程安全。
旧方法
在我们讨论有趣的东西之前,让我们先看看如何在没有.NET 的Lazy<T>
类的情况下尝试做这些事情。
通常,当你设计一个类时,你可能会从这样的代码开始:
您最终可能会发现,随着需要实例化的事物数量的增加,创建对象时的性能会显著下降。
在这种情况下,您可能会决定延迟加载该类的组件Starship
。也就是说,您可能决定仅在需要时才实例化它们。
典型版本如下:
那里有很多行。值得庆幸的是,这可以稍微压缩一下:
好吧,尽管可能不是特别容易阅读,但至少它是简洁的。
然而,扩展版本和简洁版本都存在线程问题。
如果两个调用者尝试获取同一个属性,则有可能其中一个调用者通过了空值检查,然后其线程进入休眠状态,而另一个线程也通过了该空值检查。在这种情况下,ExpensiveWarpCore
会创建两个 的实例,然后将其赋值给_warpCore
。这可能不成问题,也可能造成严重后果。
为了完全解决这个限制,您需要执行以下操作:
虽然从技术上讲这更安全,但您可以开始看到,当您引入新的延迟加载属性时,在您的类中多次执行此操作会变得乏味,并使人们倾向于浏览代码。
略读是不好的,并且会让错误隐藏起来,所以让我们寻找更好的方法。
引入 Lazy<T>
.NET 提供了一个名为的通用类Lazy
,它允许您在第一次请求对象的值时延迟实例化对象。
让我们使用以下方法看一下相同的代码Lazy<T>
:
有趣的是,我们将复杂性从属性获取器中移出并将其放在支持字段中。
让我们看一下这个惰性初始化程序:
new Lazy<WarpCore>(() => new ExpensiveWarpCore(), true)
首先,我们调用构造函数Lazy
并提供一个泛型类型参数,告诉类它将提供一个WarpCore
实例。
接下来,我们传入一个Func<WarpCore>
参数,该参数将被调用来创建所需的实例。在本例中,我们只是调用了ExpensiveWarpCore
构造函数。请注意,如果我们只是调用默认构造函数WarpCore
而不是ExpensiveWarpCore
,则甚至不需要指定这个Func
值。
最后,我们将一个true
布尔值传递给最后一个参数,表明该实例应该是线程安全的。
结束语
您只需几行代码就能看到如何Lazy<T>
在第一次使用对象时安全、简洁地实例化对象,并且如果愿意的话,还可以以线程安全的方式执行此操作。
和任何事情一样,使用 Lazy 也有一些弊端。首先,这些弊端涉及到语法,对于新开发者来说,这些语法可能难以阅读。
总而言之,Lazy
我强烈建议将其添加到您的标准实践中。它的缺点很小,而且能够将简单的模式标准化,这是一个巨大的优势。
文章“在 C# 中变得懒惰”首先出现在Kill All Defects上。
鏂囩珷鏉ユ簮锛�https://dev.to/integerman/getting-lazy-in-c-4dk5