C#如何使用Microsoft.Extensions.ObjectPool实现对象池化

来源:APP编程网作者:河北彩花头衔:网络博主
导读:本期聚焦于小伙伴创作的《C#如何使用Microsoft.Extensions.ObjectPool实现对象池化》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C#如何使用Microsoft.Extensions.ObjectPool实现对象池化》有用,将其分享出去将是对创作者最好的鼓励。

对象池化的核心作用

在C#应用开发中,部分对象的创建和销毁成本较高,比如数据库连接对象、网络请求对象、复杂计算的中间对象等。如果每次使用都重新创建,使用完就销毁,会频繁触发垃圾回收,增加系统开销。对象池化的核心思路是预先创建一批对象放在池中,需要使用的时候从池中获取,使用完之后归还到池中,避免重复创建和销毁,从而提升应用性能。

C#如何使用Microsoft.Extensions.ObjectPool实现对象池化

Microsoft.Extensions.ObjectPool基础介绍

Microsoft.Extensions.ObjectPool是.NET官方提供的对象池抽象库,位于Microsoft.Extensions.ObjectPool命名空间下,它定义了对象池的核心接口和默认实现,开发者可以直接使用,也可以根据需求自定义对象池策略。

核心接口与类

  • ObjectPool<T>:对象池的抽象基类,提供了Get和Return方法,分别用于从池中获取对象和归还对象到池中。
  • IPooledObjectPolicy<T>:对象池策略接口,定义了对象的创建和重置逻辑,需要实现Create和Return方法。
  • DefaultObjectPool<T>:默认的对象池实现类,基于IPooledObjectPolicy<T>策略工作。
  • DefaultPooledObjectPolicy<T>:默认的对象池策略,适用于无参构造函数创建的对象,归还时不做额外处理。

基础使用步骤

第一步:安装依赖包

首先需要在项目中安装Microsoft.Extensions.ObjectPool的NuGet包,可以通过NuGet包管理器或者命令行安装:

dotnet add package Microsoft.Extensions.ObjectPool

第二步:使用默认对象池

如果对象可以通过无参构造函数创建,且归还时不需要额外处理,可以直接使用默认的对象池策略。以下是一个简单的示例,池化一个自定义的StringBuilder对象:

using Microsoft.Extensions.ObjectPool;
using System.Text;

// 定义需要池化的对象类型
public class PooledStringBuilder
{
    public StringBuilder Builder { get; } = new StringBuilder();
}

class Program
{
    static void Main()
    {
        // 创建默认的对象池,使用DefaultPooledObjectPolicy
        var pool = new DefaultObjectPool<PooledStringBuilder>(new DefaultPooledObjectPolicy<PooledStringBuilder>());
        
        // 从池中获取对象
        var pooledObj = pool.Get();
        try
        {
            pooledObj.Builder.Append("Hello ");
            pooledObj.Builder.Append("ObjectPool");
            Console.WriteLine(pooledObj.Builder.ToString()); // 输出 Hello ObjectPool
        }
        finally
        {
            // 使用完之后归还到池中
            pool.Return(pooledObj);
        }
        
        // 再次获取对象,此时会复用之前归还的对象
        var anotherObj = pool.Get();
        Console.WriteLine(anotherObj.Builder.Length); // 输出 0,因为默认策略归还时不重置,这里需要手动处理,实际场景建议自定义策略
        pool.Return(anotherObj);
    }
}

第三步:自定义对象池策略

默认策略在对象归还时不会重置对象状态,实际使用中通常需要自定义策略,在对象归还时重置状态,避免脏数据。以下是一个自定义StringBuilder对象池策略的示例:

using Microsoft.Extensions.ObjectPool;
using System.Text;

// 自定义对象池策略
public class StringBuilderPooledPolicy : IPooledObjectPolicy<StringBuilder>
{
    // 创建新对象的方法
    public StringBuilder Create()
    {
        return new StringBuilder();
    }

    // 对象归还时的重置方法,返回true表示对象可以放回池中,false表示对象需要被丢弃
    public bool Return(StringBuilder obj)
    {
        // 重置StringBuilder的长度,清空内容
        obj.Clear();
        return true;
    }
}

class Program
{
    static void Main()
    {
        // 使用自定义策略创建对象池
        var pool = new DefaultObjectPool<StringBuilder>(new StringBuilderPooledPolicy());
        
        // 第一次获取对象并使用
        var sb1 = pool.Get();
        sb1.Append("First use");
        Console.WriteLine(sb1.ToString()); // 输出 First use
        pool.Return(sb1);
        
        // 第二次获取对象,此时对象已经被重置
        var sb2 = pool.Get();
        Console.WriteLine(sb2.Length); // 输出 0,说明已经被清空
        sb2.Append("Second use");
        Console.WriteLine(sb2.ToString()); // 输出 Second use
        pool.Return(sb2);
    }
}

实际业务场景示例

假设我们有一个接口需要频繁处理字符串拼接操作,每次拼接都需要创建StringBuilder对象,使用对象池优化后的代码如下:

using Microsoft.Extensions.ObjectPool;
using System.Text;

public class StringProcessor
{
    private readonly ObjectPool<StringBuilder> _stringBuilderPool;

    // 通过构造函数注入对象池,实际项目中可以结合依赖注入使用
    public StringProcessor(ObjectPool<StringBuilder> stringBuilderPool)
    {
        _stringBuilderPool = stringBuilderPool;
    }

    // 处理字符串拼接的方法
    public string ProcessStrings(params string[] parts)
    {
        var sb = _stringBuilderPool.Get();
        try
        {
            foreach (var part in parts)
            {
                sb.Append(part);
                sb.Append(' ');
            }
            return sb.ToString().Trim();
        }
        finally
        {
            // 无论是否发生异常,都归还对象到池中
            _stringBuilderPool.Return(sb);
        }
    }
}

class Program
{
    static void Main()
    {
        // 创建对象池
        var pool = new DefaultObjectPool<StringBuilder>(new StringBuilderPooledPolicy());
        var processor = new StringProcessor(pool);
        
        // 多次调用处理方法
        Console.WriteLine(processor.ProcessStrings("Hello", "World")); // 输出 Hello World
        Console.WriteLine(processor.ProcessStrings("ObjectPool", "Test")); // 输出 ObjectPool Test
    }
}

使用注意事项

  • 对象池适合池化创建成本高、可重用的对象,对于轻量级对象比如int、string等,使用对象池反而会增加开销。
  • 自定义策略的Return方法需要正确重置对象状态,避免出现脏数据影响后续使用。
  • 对象归还到池中后,不要再继续使用该对象,否则会导致不可预期的问题。
  • 如果对象池中的对象长时间不用,部分实现可能会有清理机制,具体可以参考对应实现的文档。

结合依赖注入使用

在实际的.NET Core/ASP.NET Core项目中,可以将对象池注册到依赖注入容器中,方便全局使用:

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.ObjectPool;

// 自定义策略类同上 StringBuilderPooledPolicy

class Program
{
    static void Main()
    {
        var services = new ServiceCollection();
        // 注册对象池,使用自定义策略
        services.AddSingleton<ObjectPool<StringBuilder>>(sp => 
        {
            var policy = new StringBuilderPooledPolicy();
            return new DefaultObjectPool<StringBuilder>(policy);
        });
        
        // 注册业务服务
        services.AddTransient<StringProcessor>();
        
        var serviceProvider = services.BuildServiceProvider();
        var processor = serviceProvider.GetRequiredService<StringProcessor>();
        
        Console.WriteLine(processor.ProcessStrings("DI", "Test")); // 输出 DI Test
    }
}

C#Microsoft_Extensions_ObjectPool对象池化ObjectPool修改时间:2026-07-21 15:30:52

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。