UnsafeAccessor介绍
.NET 8 引入的 UnsafeAccessor
特性是一种无需反射即可高效访问类私有成员(如字段、方法、属性等)的新机制。它通过静态外部方法结合运行时生成的底层访问逻辑,显著提升了性能并支持 AOT(提前编译)场景。
其核心在于:
- 访问私有成员:支持直接访问其他类的私有字段、方法(包括构造方法)、属性等,即使这些成员不属于当前程序集。
- 高性能:运行时生成的访问逻辑几乎与原生代码性能相当,远远优于传统反射方法(文章最后会有Benchmark测试对比)。
- AOT 友好:无需依赖动态代码生成(如
Emit
),适用于需要 AOT 编译的场景(如 iOS/Android 应用)
传统访问私有成员的方法
使用Reflection反射访问类中私有变量或方法:
using System.Reflection;
using ConsoleApp1;
var example = new Example();
var methodResult = typeof(Example).GetMethod("Method", BindingFlags.Instance | BindingFlags.NonPublic)
!.Invoke(example, Array.Empty<object>());
var fieldResult = typeof(Example).GetField("Field", BindingFlags.Instance | BindingFlags.NonPublic)
!.GetValue(example);
Console.WriteLine(methodResult);
Console.WriteLine(fieldResult);
public class Example
{
private string Field = "test";
private string Method()
{
return "Test";
}
}
使用UnsafeAccessor访问私有成员
在Net8版本中用新的方式实现:
using System.Runtime.CompilerServices;
var example = new Example();
var methodResult = Caller.GetMethod(example);
var fieldResult = Caller.GetField(example);
Console.WriteLine(methodResult);
Console.WriteLine(fieldResult);
public class Caller
{
[UnsafeAccessor(UnsafeAccessorKind.Method,Name = "Method")]
public static extern string GetMethod(Example example);
[UnsafeAccessor(UnsafeAccessorKind.Field,Name = "Field")]
public static extern ref string GetField(Example example);
}
public class Example
{
private string Field = "test";
private string Method()
{
return "Test";
}
}
基准测试对比
使用Benchmark测试两种方式性能:
using System.Reflection;
using BenchmarkDotNet.Attributes;
namespace ConsoleApp1;
public class ReflectionBenchmarks
{
private readonly Example _example = new();
private static readonly MethodInfo CachedMethod=typeof(Example).
GetMethod("Method", BindingFlags.Instance | BindingFlags.NonPublic)!;
[Benchmark]
public string GetMethod_Reflection()
{
return (string)_example.GetType().GetMethod("Method", BindingFlags.Instance | BindingFlags.NonPublic)
!.Invoke(_example, Array.Empty<object>())!;
}
[Benchmark]
public string GetMethod_ReflectionCached()
{
return (string)CachedMethod.Invoke(_example, Array.Empty<object>())!;
}
[Benchmark]
public string GetMethod_Unsafe()
{
return Caller.GetMethod(_example);
}
}
测试结果:
从结果中可以看出,Unsafe方法性能是完全的癫狂,甚至和调用一个空方法时间相差无几。
总的来说,UnsafeAccessor
为需要突破封装性但追求高性能的场景提供了新选择,尤其适用于框架开发和 AOT 环境。