实施一个"LazyProperty"类-这是个好主意吗?
-
22-07-2019 - |
题
我经常发现自己写的一个属性,是评估懒洋洋地。是这样的:
if (backingField == null)
backingField = SomeOperation();
return backingField;
它不是太多的代码,但它不会重复了很多,如果你有很多的属性。
我想到的是界定一类称为LazyProperty:
public class LazyProperty<T>
{
private readonly Func<T> getter;
public LazyProperty(Func<T> getter)
{
this.getter = getter;
}
private bool loaded = false;
private T propertyValue;
public T Value
{
get
{
if (!loaded)
{
propertyValue = getter();
loaded = true;
}
return propertyValue;
}
}
public static implicit operator T(LazyProperty<T> rhs)
{
return rhs.Value;
}
}
这将使我的初始化的一个领域是这样的:
first = new LazyProperty<HeavyObject>(() => new HeavyObject { MyProperty = Value });
然后身体的财产,可减少:
public HeavyObject First { get { return first; } }
这将可以使用的大多数公司,因为它会进入一个共同类库共享通过我们的大多数产品。
我无法决定这是否是一个好主意,或者没有。我认为解决方案具有一些优点,如:
- 不少代码
- 漂亮的码
在缺点,这将是难以看码,并确定到底发生什么事-尤其是如果开发人员不熟悉的LazyProperty类。
你怎么想?这是一个很好的想法或者我应该放弃它?还是隐含的操作者是一个好主意,或者你会更喜欢使用价值的属性明确如果你应该使用这类?
意见和建议表示欢迎:-)
解决方案
只是过于迂腐:
你的提议的解决方案,以避免重复代码:
private LazyProperty<HeavyObject> first =
new LazyProperty<HeavyObject>(() => new HeavyObject { MyProperty = Value });
public HeavyObject First {
get {
return first;
}
}
实际上是更符于代码,你不想再重复一遍:
private HeavyObject first;
public HeavyObject First {
get {
if (first == null) first = new HeavyObject { MyProperty = Value };
return first;
}
}
除此之外,我认为隐含的铸造成的代码非常难以理解。我不会猜到的一个方法,简单地返回第一,实际上最终创建一个HeavyObject.我想至少有下降的隐性转换和返回的第一次。值的财产。
其他提示
不这样做。
一般采用这样的懒惰的初始化属性是一个有效的设计选择在一种情况:时 SomeOperation();
是一种昂贵的运作(I/O,就像当它需要一个数据库的打击,或计算)以及当你肯定你会常常不需要对其进行访问。
这就是说,通过默认你应该去渴望的初始化,及时探查说这是你的瓶颈,然后改变它对懒惰的初始化。
如果你觉得敦促以创造一种抽象,它的气味。
你肯定会至少要 LazyPropery<T>
是一个值的类型,否则你已经加入存储器和GC压力为每一个"延迟装载"酒店在你的系统。
此外,那么多线程的情况下?考虑两个线的请求的财产,在同一时间。没有锁,您可以创建两个实例为基础的财产。为了避免锁定在常见的情况下,你想要做一双重检查锁。
我喜欢第一个代码,是因为a)它是一种常见的模式与性质,我立即了解它,并b)点,你提出:那没有隐藏的魔法,你必须去看了解,当值正得到的。
我喜欢这个想法在于,它是多少代码和更优雅,但我非常担心的是,它变成硬盘来看待它,并告诉什么。只有这样,我将考虑它是有一个《公约》为设置的变量使用了"懒惰"的方式,并且还发表评论的任何地方使用它。现在也不会是一个编译器或任何强制执行这些规则,所以仍然情况因人而异。
在结束时,我决定这样归结到谁将是看它和质量的那些程序员。如果你可以信任你的同胞开发人员使用它的权利和评论良好,然后去它,但是,如果没有,你最好这样做的一个很容易理解和遵循的方式。/2美分的代我的
我不认为令人担忧的关于开发人员不理解的是一个很好的论据反对这样做像这样的东西...
如果你认为然后你什么也做不了恐惧的人不了解你做了什么
你可以写一教程或什么东西在一个中央资料库,我们在这里的维基于这些类型的笔记
总体而言,我认为这是一个很好的执行情况的想法(不想要开始一场辩论是否延迟加载是一个很好的想法或不)
我做什么在这种情况下是我创建了一个 Visual Studio代码.我想这就是你真的应该做的。
例如,当我创造的ASP.NET 控制,我常常有数据,都存储在电视图状态很多,所以我创造了一段代码这样的:
public Type Value
{
get
{
if(ViewState["key"] == null)
ViewState["key"] = someDefaultValue;
return (Type)ViewState["key"];
}
set{ ViewState["key"] = value; }
}
这种方式,可以很容易地创造了只有一点点的工作(限定的类型,关键,名和默认值)。它可重复使用的,但是你没有缺点的复杂的代码,其他的开发者可能不了解。
我喜欢你的解决方案,因为它是非常聪明但我不认为你赢得很多的使用。懒惰的装载一个私人领域在公共财产的绝对是一个地方在那里的代码可以被重复。但是这总是让我吃惊作为一种模式使用,而不是代码,需要重构成一个共同的地方。
你的方法可以成为一个令人关切的未来,如果你做任何序列化。它也是更多的混乱开始明白你是什么做的定义的类型。
总的来说,我赞赏你的尝试,并赞赏其聪明但会建议你回到你原来的解决方案的理由如上述。
就个人而言,我不认为LazyProperty类是提供足够的价值来证明使用这尤其是考虑到存在的缺陷使用价值的类型(如肯特所提到的).如果你需要其他功能(比如让很多线程的),它可能有正当理由作为ThreadSafeLazyProperty类。
关于隐性的,我喜欢"价值的财产"更好。这是一个小小的更多的输入,但更多的我清楚。
我认为这是一个有趣的想法。第一,我会建议你隐藏的懒财产调用代码,你不要泄漏到你域模型,它是懒惰。你做的隐含的操作者所以保持。
我喜欢你如何使用这种方法来处理和抽象的程的细节锁的例子。如果你这样做,那么我认为有价值和优点。如果你做的加锁看出来的双重锁定模式很容易获得这是错误的。
你可以使用C#迭代器。下面的文章介绍样品的使用情况和优点在使用它。