【CSharp】延迟初始化(Lazy)

参考
https://www.jb51.net/article/202143.htm

1. 什么是延迟初始化

延迟初始化是一种将对象的创建延迟到第一次需要用时的技术,换句话说,对象的初始化是发生在真正需要的时候才执行。通过使用延迟初始化技术,可以避免应用程序不必要的计算和内存消耗。

2. 简单使用场景

考虑下面两个类,CustomerOrderCustomer类包含了一个Orders属性。一个人肯定会有很多的订单,也就意味着它可能包含了很多的数据,甚至还需要连接数据库去获取Orders记录。在这种场景下,没必要给customer集合中的所有人都带上完整的Orders。因为这个初始化的开销是巨大的,优化点就是在初始化不加载Orders,直到某些customer真的需要Orders时才按需灌入。

3. 使用 System.Lazy

Lazy<IEnumerable<Order>> orders = new Lazy<IEnumerable<Order>>();
IEnumerable<Order> result = lazyOrders.Value;

现在,考虑下面的两个类:AuthorBlog,一个作者可以写很多文章,所以这两个类之间是一对多的关系,下面的代码片段展示了这种关系。

public class Author
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Address { get; set; }
    public List<Blog> Blogs { get; set; }
}

public class Blog
{
    public int Id { get; set; }
    public string Title { get; set; }
    public DateTime PublicationDate { get; set; }
}

现在假定在用户界面仅需展示Author的基础信息,比如说:(firstname,lastname,address),在这种场景下,给Author对象加载Blogs集合是毫无意义的,当真的需要加载Blogs时,执行Blogs.Value即可立即执行,下面展示了Lazy<Blog> Blogs的用法。

public class Author
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Address { get; set; }
    public Lazy<IList<Blog>> Blogs => new Lazy<IList<Blog>>(() => Author.GetBlogs(this.Id));
    
    private static IList<Blog> GetBlogs(int Id)
    {
    	//Write code here to retrieve all blog details for an author.
    }
}

4. 使用Lazy实现单例模式

public sealed class StateManager
{
	private StateManager()
	{
	}

    public static StateManager Instance => Nested.obj;
    
	private class Nested
	{
		static Nested()
		{
		}
		internal static readonly StateManager obj = new StateManager();
	}
}

5. System.Lazy

  • 默认设置下,Lazy 类的所有公共和受保护的成员都是线程安全的,可从多个线程同时使用。

5.1 构造函数

  • public Lazy ();
    延迟初始化发生时,对应类型的无参构造被调用。
void Main()
{
	var lazy = new Lazy<A>();
	Console.WriteLine("================");
	Console.WriteLine(lazy.Value.ToString());
}

class A
{
	public A()
	{
		Console.WriteLine("A: Constructor");
	}

	public override string ToString()
	{
		return nameof(A) + ":" + nameof(ToString);
	}
}

================
A: Constructor
A:ToString

  • public Lazy (bool isThreadSafe);
    延迟初始化发生时,对应类型的无参构造与指定的模式被调用。
    isThreadSafe = true 创建的实例是线程安全的
    isThreadSafe = false 创建的实例是非线程安全的
  • Lazy(Func)
    延迟初始化发生时,使用指定的方法进行初始化。
void Main()
{
	var lazy = new Lazy<A>(CreateA);
	Console.WriteLine("================");
	Console.WriteLine(lazy.Value.ToString());
}

static A CreateA()
{
	Console.WriteLine(nameof(CreateA));
	return new A();
}

class A
{
	public A()
	{
		Console.WriteLine("A: Constructor");
	}

	public override string ToString()
	{
		return nameof(A) + ":" + nameof(ToString);
	}
}

================
CreateA
A: Constructor
A:ToString

  • public Lazy (System.Threading.LazyThreadSafetyMode mode);
    延迟初始化发生时,使用指定的线程安全枚举值进行初始化。

5.2 属性

  • IsValueCreated 指示真实初始化是否发生
void Main()
{
	var lazy = new Lazy<A>();
	Console.WriteLine(nameof(lazy.IsValueCreated) + ": " + lazy.IsValueCreated);
	Console.WriteLine("================");
	Console.WriteLine(lazy.Value.ToString());
	Console.WriteLine(nameof(lazy.IsValueCreated) + ": " + lazy.IsValueCreated);
}

class A
{
	public A()
	{
		Console.WriteLine("A: Constructor");
	}

	public override string ToString()
	{
		return nameof(A) + ":" + nameof(ToString);
	}
}

IsValueCreated: False
================
A: Constructor
A:ToString
IsValueCreated: True

  • Value 获取真实类型的值

6. 自定义实现延迟加载

void Main()
{
	var person = new Person();
	Console.WriteLine("+++++++++++++++++++++++");
	foreach (var phone in person.Phones)
	{
		Console.WriteLine(phone.ToString());
	}
	Console.WriteLine();

	var personLazy = new PersonLazy();
	Console.WriteLine("+++++++++++++++++++++++");
	Console.WriteLine("调用属性");
	var phones = personLazy.Phones;
	Console.WriteLine("+++++++++++++++++++++++");
	Console.WriteLine("执行属性");
	foreach (var phone in personLazy.Phones())
	{
		Console.WriteLine(phone.ToString());
	}
}

class Person
{
	public List<Phone> Phones {get;set;} = new List<Phone>();
	
	public Person()
	{
		System.Console.WriteLine(nameof(Person) + " is created.");
		Console.WriteLine("+++++++++++++++++++++++");
		this.Phones.Add(new Phone(){ID = "11111111111111"});
		this.Phones.Add(new Phone(){ID = "22222222222222"});
		this.Phones.Add(new Phone(){ID = "33333333333333"});
		this.Phones.Add(new Phone(){ID = "44444444444444"});
		this.Phones.Add(new Phone(){ID = "55555555555555"});
	}
}

class PersonLazy
{
	private List<Phone> phones = new List<Phone>();
	public Func<List<Phone>> Phones => GetPhones;

	public PersonLazy()
	{
		System.Console.WriteLine(nameof(PersonLazy) + " is created.");
		Console.WriteLine("+++++++++++++++++++++++");
	}
	
	private List<Phone> GetPhones()
	{
		var phones = new List<Phone>();
		phones.Add(new Phone() { ID = "11111111111111" });
		phones.Add(new Phone() { ID = "22222222222222" });
		phones.Add(new Phone() { ID = "33333333333333" });
		phones.Add(new Phone() { ID = "44444444444444" });
		phones.Add(new Phone() { ID = "55555555555555" });
		return phones;
	}
}

class Phone
{
	public string ID {get;set;}
	public Phone()
	{
		System.Console.WriteLine(nameof(Phone) + " is created.");
	}

	public override string ToString()
	{
		return nameof(Phone) + ": " + this.ID;
	}
}

Person is created.
+++++++++++++++++++++++
Phone is created.
Phone is created.
Phone is created.
Phone is created.
Phone is created.
+++++++++++++++++++++++
Phone: 11111111111111
Phone: 22222222222222
Phone: 33333333333333
Phone: 44444444444444
Phone: 55555555555555

PersonLazy is created.
+++++++++++++++++++++++
+++++++++++++++++++++++
调用属性
+++++++++++++++++++++++
执行属性
Phone is created.
Phone is created.
Phone is created.
Phone is created.
Phone is created.
Phone: 11111111111111
Phone: 22222222222222
Phone: 33333333333333
Phone: 44444444444444
Phone: 55555555555555

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhy29563

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值