C# 延迟加载技术详解
|
admin
2025年2月20日 9:2
本文热度 354
|
什么是延迟加载?
延迟加载(Lazy Loading)是一种设计模式,它允许推迟对象的初始化,直到该对象真正被使用时才进行加载。这种技术可以帮助提高应用程序的性能和资源利用效率。
延迟加载的主要优点
- 减少内存消耗
- 提高应用程序启动速度
- 按需加载资源
- 降低系统开销
C#中的延迟加载实现方式
使用 Lazy 类
Lazy<T>
是.NET Framework 4.0引入的泛型类,提供了最简单的延迟加载实现。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AppLazy
{
publicclass UserProfile
{
// 延迟加载的复杂对象
// ThreadSafetyMode.ExecutionAndPublication 确保线程安全
private Lazy<ExpensiveResource> _expensiveResource;
public UserProfile()
{
// 使用 LazyThreadSafetyMode 确保线程安全
_expensiveResource = new Lazy<ExpensiveResource>(
() => new ExpensiveResource(),
LazyThreadSafetyMode.ExecutionAndPublication
);
}
public ExpensiveResource GetResource()
{
// 只有在调用Value时才真正创建对象
return _expensiveResource.Value;
}
}
publicclass ExpensiveResource
{
public Guid ResourceId { get; } = Guid.NewGuid();
public ExpensiveResource()
{
// 模拟复杂的初始化过程
Console.WriteLine($"正在初始化复杂资源 {ResourceId}...");
Thread.Sleep(2000); // 模拟耗时操作
Console.WriteLine($"复杂资源 {ResourceId} 初始化完成。");
}
}
}
namespace AppLazy
{
internal class Program
{
static void Main(string[] args)
{
// 创建 UserProfile 实例
UserProfile userProfile = new UserProfile();
Console.WriteLine("创建 UserProfile 实例,但尚未初始化资源...");
// 第一次访问 ExpensiveResource
Console.WriteLine("第一次获取资源:");
ExpensiveResource resource1 = userProfile.GetResource();
// 再次访问,不会重复初始化
Console.WriteLine("第二次获取资源:");
ExpensiveResource resource2 = userProfile.GetResource();
// 验证是否是同一个实例
Console.WriteLine($"两次获取的资源是否是同一个实例:{object.ReferenceEquals(resource1, resource2)}");
}
}
}

延迟加载集合
namespace AppLazy
{
publicclass LazyCollection
{
// 使用Lazy<List<T>>延迟加载集合
private Lazy<List<string>> _lazyItems;
public LazyCollection()
{
_lazyItems = new Lazy<List<string>>(() => LoadItems());
}
private List<string> LoadItems()
{
Console.WriteLine("正在加载数据集合...");
// 模拟耗时的数据加载过程,比如从数据库或文件中读取
System.Threading.Thread.Sleep(1000); // 模拟1秒加载时间
returnnew List<string> { "Item1", "Item2", "Item3" };
}
public List<string> GetItems()
{
return _lazyItems.Value;
}
public static void Main(string[] args)
{
LazyCollection collection = new LazyCollection();
Console.WriteLine("创建集合实例,但尚未加载数据...");
// 第一次访问时会触发数据加载
Console.WriteLine("第一次获取数据:");
List<string> items = collection.GetItems();
foreach (var item in items)
{
Console.WriteLine(item);
}
// 再次获取数据(不会重复加载)
Console.WriteLine("\n第二次获取数据:");
items = collection.GetItems();
foreach (var item in items)
{
Console.WriteLine(item);
}
}
}
}

自定义延迟加载实现
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AppLazy
{
// 定义一个演示用的类
publicclass ExpensiveResource
{
public Guid Id { get; privateset; }
public DateTime CreatedAt { get; privateset; }
public ExpensiveResource()
{
Id = Guid.NewGuid();
CreatedAt = DateTime.Now;
Console.WriteLine($"ExpensiveResource 实例被创建,ID: {Id}");
}
public void DoSomething()
{
Console.WriteLine($"正在使用资源 {Id}");
}
}
}
namespace AppLazy
{
publicclass Program
{
public static void Main(string[] args)
{
// 创建一个CustomLazyLoader实例
CustomLazyLoader<ExpensiveResource> lazyLoader = new CustomLazyLoader<ExpensiveResource>();
Console.WriteLine("准备获取实例...");
// 第一次调用会创建实例
ExpensiveResource resource1 = lazyLoader.GetInstance();
resource1.DoSomething();
Console.WriteLine("再次获取实例...");
// 第二次调用会返回同一个实例
ExpensiveResource resource2 = lazyLoader.GetInstance();
resource2.DoSomething();
// 验证两次获取的是同一个实例
Console.WriteLine($"两次获取的实例是否相同:{ReferenceEquals(resource1, resource2)}");
}
}
// 自定义延迟加载器
publicclass CustomLazyLoader<T> where T :new()
{
private T _instance;
privatebool _isInitialized = false;
private readonly object _lock = new object();
public T GetInstance()
{
// 线程安全的双重检查锁定模式
if (!_isInitialized)
{
lock (_lock)
{
if (!_isInitialized)
{
_instance = new T();
_isInitialized = true;
}
}
}
return _instance;
}
}
}

实际应用场景
数据库查询延迟加载
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AppLazy
{
// 用户实体类
publicclass User
{
publicint Id { get; set; }
publicstring Username { get; set; }
publicstring Email { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using LiteDB;
namespace AppLazy
{
publicclass UserRepository : IDisposable
{
private readonly string _dbPath;
private readonly object _lock = new object();
public UserRepository(string dbPath = "users.db")
{
_dbPath = dbPath;
}
private LiteDatabase CreateDatabaseConnection()
{
try
{
// 直接使用路径,不再使用 ConnectionString
returnnew LiteDatabase(_dbPath);
}
catch (IOException ex)
{
Console.WriteLine($"数据库连接错误: {ex.Message}");
throw;
}
}
// 修改所有数据库操作方法
public List<User> FetchUsersFromDatabase()
{
lock (_lock)
{
using (var database = CreateDatabaseConnection())
{
var collection = database.GetCollection<User>("users");
returnnew List<User>(collection.FindAll());
}
}
}
public void AddUser(User user)
{
lock (_lock)
{
using (var database = CreateDatabaseConnection())
{
var collection = database.GetCollection<User>("users");
collection.Insert(user);
}
}
}
public User GetUserById(int id)
{
lock (_lock)
{
using (var database = CreateDatabaseConnection())
{
var collection = database.GetCollection<User>("users");
return collection.FindById(id);
}
}
}
public void Dispose()
{
// 如果需要额外的清理逻辑,可以在这里添加
GC.SuppressFinalize(this);
}
}
}
该文章在 2025/2/20 9:33:26 编辑过