C#惰性加载自动属性

在C#中,

有没有办法将一个自动属性变成一个惰性加载自动属性与指定的默认值?

本质上,我试图把这个…

private string _SomeVariable public string SomeVariable { get { if(_SomeVariable == null) { _SomeVariable = SomeClass.IOnlyWantToCallYouOnce(); } return _SomeVariable; } } 

到不同的地方,我可以指定默认,并自动处理其余的…

 [SetUsing(SomeClass.IOnlyWantToCallYouOnce())] public string SomeVariable {get; private set;} 

不,那里没有。 自动实现的属性仅用于实现最基本的属性:使用getter和setter的后台字段。 它不支持这种types的自定义。

但是,您可以使用4.0 Lazy<T>types来创build此模式

 private Lazy<string> _someVariable =new Lazy<string>(SomeClass.IOnlyWantToCallYouOnce); public string SomeVariable { get { return _someVariable.Value; } } 

这个代码将在第一次调用Valueexpression式时_someVariable地计算_someVariableValue 。 它只会被计算一次,并会cachingValue属性未来使用的Value

可能最简洁的你可以使用空合并运算符:

 get { return _SomeVariable ?? (_SomeVariable = SomeClass.IOnlyWantToCallYouOnce()); } 

在C#6中有一个叫做Expression Bodied Auto-Properties的新特性 ,它可以让你把它写得更干净些:

 public class SomeClass { private Lazy<string> _someVariable = new Lazy<string>(SomeClass.IOnlyWantToCallYouOnce); public string SomeVariable { get { return _someVariable.Value; } } } 

现在可以写成:

 public class SomeClass { private Lazy<string> _someVariable = new Lazy<string>(SomeClass.IOnlyWantToCallYouOnce); public string SomeVariable => _someVariable.Value; } 

不是这样的,参数的属性值必须是常数,你不能调用代码(即使是静态代码)。

然而,你可以用PostSharp的方面来实现一些东西。

去看一下:

PostSharp

这是我的解决你的问题的实现。 基本上这个想法是一个属性,它将在第一次访问时由函数设置,随后的访问将产生与第一次访问相同的返回值。

 public class LazyProperty<T> { bool _initialized = false; T _result; public T Value(Func<T> fn) { if (!_initialized) { _result = fn(); _initialized = true; } return _result; } } 

然后使用:

 LazyProperty<Color> _eyeColor = new LazyProperty<Color>(); public Color EyeColor { get { return _eyeColor.Value(() => SomeCPUHungryMethod()); } } 

当然也有传递函数指针的开销,但是它为我做了这个工作,与重复运行该方法相比,我没有注意到太多开销。

我不认为这是纯粹的C#可能。 但是你可以使用像PostSharp这样的IL重写器。 例如,它允许您根据属性在函数之前和之后添加处理程序。

https://github.com/bcuff/AutoLazy使用Fody给你这样的东西;

 public class MyClass { // This would work as a method, eg GetSettings(), as well. [Lazy] public static Settings Settings { get { using (var fs = File.Open("settings.xml", FileMode.Open)) { var serializer = new XmlSerializer(typeof(Settings)); return (Settings)serializer.Deserialize(fs); } } } [Lazy] public static Settings GetSettingsFile(string fileName) { using (var fs = File.Open(fileName, FileMode.Open)) { var serializer = new XmlSerializer(typeof(Settings)); return (Settings)serializer.Deserialize(fs); } } }