C# 延迟加载技术详解
				
									
					
					
						|  | 
							admin 2025年2月20日 9:2
								本文热度 2103 | 
					
				 
				什么是延迟加载?
延迟加载(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 编辑过