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

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