• Lazy<T>的应用之类内部字段与C#延迟加载


        延迟加载主要应用在以下场景:

    数据层 – ADO.NET或Entity Framework等ORM
    反射 – 加载assemblies, types, MEF
    缓存对象,领域实体

        下面以领域实体为例, 在实体中我们经常检查某个属性下字段是否为空引用. 如果是空的话,计算或填充这个字段. 像这样:

       1:      /// <summary>
       2:      /// Order
       3:      /// </summary>
       4:      public class Order
       5:      { 
       6:          private Customer _customer;
       7:          /// <summary>
       8:          /// Gets the customer.
       9:          /// </summary>
      10:          public Customer Customer
      11:          {
      12:              get
      13:              {
      14:                  if (_customer == null)
      15:                  {
      16:                      _customer = new Customer();
      17:                  } return _customer;
      18:              }
      19:          }
      20:          /// <summary>
      21:          /// Prints the label.
      22:          /// </summary>
      23:          /// <returns></returns>
      24:          public string PrintLabel()
      25:          {
      26:              return Customer.CompanyName + "\n" + Customer.Address;
      27:          }
      28:      }

    如果PrintLabel方法写成这样:

       1:          public string PrintLabel()
       2:          {
       3:              string result = _customer.CompanyName; // probably results in a NullReferenceException    
       4:              return result + "\n" + Customer.Address; // ok to access Customer  
       5:          }

    注意上面第4行代码,可能有空引用异常. 下面我们使用Lazy<T>来解决这个问题:

       1:      /// <summary>
       2:      /// Order
       3:      /// </summary>
       4:      public class Order
       5:      {
       6:          /// <summary>
       7:          /// _customerInitializer
       8:          /// </summary>
       9:          private Lazy<Customer> _customerInitializer;
      10:   
      11:          /// <summary>
      12:          /// Initializes a new instance of the <see cref="Order"/> class.
      13:          /// </summary>
      14:          public Order()
      15:          {
      16:              _customerInitializer = new Lazy<Customer>(() => new Customer(),isThreadSafe:true);
      17:          }
      18:   
      19:          /// <summary>
      20:          /// Gets the customer.
      21:          /// </summary>
      22:          public Customer Customer
      23:          {
      24:              get{ return _customerInitializer.Value;}
      25:          }
      26:   
      27:          /// <summary>
      28:          /// Prints the label.
      29:          /// </summary>
      30:          /// <returns></returns>
      31:          public string PrintLabel()
      32:          {
      33:              string result = Customer.CompanyName; // ok to access Customer       
      34:              return result + "\n" + _customerInitializer.Value.Address; // ok to access via .Value  
      35:          }
      36:      }

    上面的代码16行,我们延迟初始化对像实例,并且设置线程安全.  Lazy<T>内部是使用Func<T>来实现的,看下面其中构造器的源代码:

       1:  public Lazy(Func<T> valueFactory, LazyThreadSafetyMode mode)
       2:  {
       3:      if (valueFactory == null) throw new ArgumentNullException("valueFactory");
       4:      this.m_threadSafeObj = Lazy<T>.GetObjectFromMode(mode);
       5:      this.m_valueFactory = valueFactory;
       6:  }

    有兴趣请自行查看.net framework中的源码. 我们还可以扩展一个LazyNotNull<T>

       1:      /// <summary>
       2:      /// LazyNotNull
       3:      /// </summary>
       4:      /// <typeparam name="T">Type</typeparam>
       5:      public class LazyNotNull<T>
       6:      {
       7:          private Lazy<T> _lazyValue = null;
       8:          private Func<T> _valueFactory = null;
       9:   
      10:          /// <summary>
      11:          /// Initializes a new instance of the <see cref="LazyNotNull&lt;T&gt;"/> class.
      12:          /// </summary>
      13:          /// <param name="valueFactory">The value factory.</param>
      14:          public LazyNotNull(Func<T> valueFactory)
      15:          {
      16:              _lazyValue = new Lazy<T>(valueFactory);
      17:              _valueFactory = valueFactory;
      18:          }
      19:   
      20:          /// <summary>
      21:          /// Gets T value.
      22:          /// </summary>
      23:          public T Value
      24:          {
      25:              get
      26:              {
      27:                  var lazyValue = _lazyValue;
      28:                  if (lazyValue.Value != null)
      29:                  {
      30:                      return lazyValue.Value;
      31:                  }
      32:                  _lazyValue = new Lazy<T>(_valueFactory);
      33:                  return default(T);
      34:              }
      35:          }
      36:      }


    希望这篇POST对您开发有帮助.
    您可能感兴趣的文章:

    .net4.0下的Lazy<T>类型简单应用
    .net3.5下使用LINQ递归算法实现简洁代码


    作者:Petter Liu
    出处:http://www.cnblogs.com/wintersun/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
    该文章也同时发布在我的独立博客中-Petter Liu Blog

  • 相关阅读:
    hackrank Sorting Array of Strings
    c programming create a file
    spine unity3D(摘自博主softimagewht)
    实现鼠标双击(OnGUI)
    使用Unity NGUIInputField组件输入时发现显示为白色就是看不到字体
    NGUI制作可滚动的文本框(摘,如有侵权,联系删除)
    Unity3d 简单的小球沿贝塞尔曲线运动(适合场景漫游使用)
    MVC简单随笔
    Unity脚本自动添加注释脚本及排版格式
    树和树的分类
  • 原文地址:https://www.cnblogs.com/wintersun/p/2265394.html
Copyright © 2020-2023  润新知