在c#延迟加载中是autoproperties?

时间:2012-01-14 10:11:05

标签: c# lazy-loading

我已经阅读了一些关于c#中延迟加载的内容,这可能看起来像一个非常基本的问题,但我想知道autoproperties是否是默认的延迟加载。例如:

public Color MyColor { get; set; }

或者我是否必须按照

的方式实施
private Color _color;
public Color MyColor
{
  get
  {
      if(_color==null)
      { 
       _color=new Color("red");
      }
      return _color;
  }
 }

由于 托马斯

6 个答案:

答案 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; }  

优点:

  1. 允许您避免使用字段/变量。使用反射,我不知道为字段设置值的方法。所以我尽可能选择属性。
  2. 缺点:

    • 调试器很可怕。该属性与哪个变量名相关联?希望微软自动使用_MyColor,但它很可能是一种神秘的东西。

    字段

    public Color MyColor;  
    

    优点:

    • 没有复杂性
    • 易于使用调试器

    缺点:

    • 我无法立即想到如何使用反射来获取和设置值。如果可能的话,那么与Lazy Property相比,可能没有任何不利因素。

    就个人而言,我每次都使用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}");