我已经阅读了一些关于c#中延迟加载的内容,这可能看起来像一个非常基本的问题,但我想知道autoproperties是否是默认的延迟加载。例如:
public Color MyColor { get; set; }
或者我是否必须按照
的方式实施private Color _color;
public Color MyColor
{
get
{
if(_color==null)
{
_color=new Color("red");
}
return _color;
}
}
由于 托马斯
答案 0 :(得分:5)
自动属性只会获得编译器生成的支持字段。
所以,这个:
public Color MyColor { get; set; }
最终会像这样结束:
private Color _color;
public Color MyColor
{
get
{
return _color;
}
set
{
_color = value;
}
}
所以他们不是懒惰的 - 你需要自己实现它。
您可以实例化支持字段,如下所示:
private Color _color = new Color("red");
使用自动属性,您可以使用构造函数设置默认值:
// in the constructor:
MyColor = new Color("red");
答案 1 :(得分:2)
不,他们不是懒惰的,一个自动财产就像这样做
private Color _color;
public Color MyColor
{
get
{
return _color;
}
set
{
_color = value;
}
}
答案 2 :(得分:2)
自动属性只是属性的通用模式的语法糖,它直接读取和写入后备字段而没有其他逻辑。
如果你想延迟加载,你需要你提供的第二种形式,你提供的第一种形式的更复杂版本,或者:
private Lazy<Color> _color = new Lazy<Color>(() => new Color("red"));
public Color MyColor
{
get
{
return _color.Value;
}
}
在这种情况下哪个更复杂,但在其他一些情况下更简单。
懒惰加载模式的变体要么忽略了安全问题(你的问题),这取决于一些事情可能仍然是线程安全的(这取决于它是否是mulitple的一个问题{{ 1}}创建发生,有些被覆盖,直到最终“赢”,并且通常不是问题,尽管如果可能存在多个并发呼叫需要考虑的事情,以允许多个呼叫到构造函数但确保只有一个“获胜”并成为使用的值,或者只允许一次调用。
这三种变体或在只有一个线程的情况下成本增加,但如果你有大量的并发呼叫,则增加安全性并降低成本,因此三者中的每一个都有它的位置。
Color
使用public Color MyColor
{
get
{
if(_color == null)
{
var c = new Color("red");//allow multiple creations but...
Interlocked.CompareExchange(ref _color, c, null);//only one write
}
return _color;
}
}
public Color MyColor
{
get
{
if(_color == null)
lock(somelock)
if(_color == null)
_color = new Color("red");//allow one creation only
return _color;
}
}
时,有一种构造函数形式,它采用Lazy<Color>
值来指示您想要的方法。
答案 3 :(得分:0)
如果你写
public Color MyColor { get; set; }
然后您的属性将始终为null
,直到您实例化它。
this.MyColor = new Color("red");
自动属性只是一种捷径。
public Color MyColor { get; set; }
与
相同private Color _MyColor;
public Color MyColor
{
get
{
return this._MyColor;
}
set
{
this._MyColor = value;
}
}
答案 4 :(得分:0)
public Color MyColor { get; set; }
public Color MyColor;
就个人而言,我每次都使用Properties,因为它还允许您在属性get / set中添加边界检查和诸如此类的东西。我不喜欢在任何地方进行检查,除非是为了防止对我正在编码的函数进行操作。
答案 5 :(得分:0)
当我们用作类成员时,延迟加载不起作用。让我向您展示类结构:
class Data
{
public string Item1 { get; set; }
public string Item2 { get; set; }
public Data()
{
this.Item1 = "Item1";
this.Item2 = "Item2";
}
}
class MyClassEager
{
public int Id { get; set; }
public Lazy<Data> data { get; set; }
public MyClassEager()
{
Id = 1;
data = new Lazy<Data>();
}
}
测试:
var temp = new MyClassEager();
Lazy<MyClassEager> myClassEager = new Lazy<MyClassEager>();
Console.WriteLine($"is myClassEager Data initialized : {myClassEager.IsValueCreated}");
var temp1 = myClassEager.Value;
Console.WriteLine($"is myClassEager Data initialized : {myClassEager.IsValueCreated}");
Console.WriteLine($"is Data data initialized : {myClassEager.Value.data.IsValueCreated}");
//why the temp2 is null here
var temp2 = myClassEager.Value.data;
//why the IsValueCreated is false here
Console.WriteLine($"is myClassEager Data data initialized : {myClassEager.Value.data.IsValueCreated}");