C#如何通过反射判断Record是否实现自定义相等比较方法
C# Record类型自定义Equals方法的反射判断方案
完全可以通过反射实现该判断,核心是识别编译器自动生成代码的专属标记。
实现原理
C#编译器为无自定义相等逻辑的Record类型自动生成相等比较相关方法时,会遵循固定规则:
- 自动生成的强类型
Equals(TRecord other)方法(IEquatable<T>接口实现)、Equals(object? obj)重写方法、GetHashCode()重写方法,都会被标记[CompilerGenerated]特性 - 如果开发者显式实现了任意签名匹配的相等比较方法,编译器就不会生成对应签名的自动实现方法,开发者手写的方法默认不会携带
[CompilerGenerated]特性
通过检查Record类型上强类型Equals方法是否携带该特性,即可准确区分是编译器自动生成还是用户自定义实现。
实现代码
首先引入必须的命名空间:
using System.Reflection; using System.Runtime.CompilerServices;
判断方法实现如下:
public static bool HasCustomEqualityImplementation(Type recordType) { // 非Record类型直接返回false,可按需调整为抛出参数异常 if (!recordType.IsRecord) return false; // 查找当前类型自身声明的强类型Equals方法:public bool Equals(当前记录类型 other) // DeclaredOnly 标记指定只查找当前类型定义的成员,不查找从父类继承的成员 MethodInfo? strongTypedEquals = recordType.GetMethod( nameof(object.Equals), BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly, binder: null, new[] { recordType }, modifiers: null); // 正常无自定义逻辑的Record一定会存在编译器生成的强类型Equals方法,若不存在则判定为自定义实现 if (strongTypedEquals == null) return true; // 方法未携带CompilerGenerated特性即为用户自定义实现 return !strongTypedEquals.IsDefined(typeof(CompilerGeneratedAttribute), inherit: false); }
结果验证
针对题目给出的示例代码,调用结果完全符合预期:
HasCustomEqualityImplementation(typeof(A)); // 返回false,A的Equals为编译器自动生成,带[CompilerGenerated]标记 HasCustomEqualityImplementation(typeof(B)); // 返回true,B的Equals为用户手写实现,无编译器生成标记
补充说明
- 该方案依赖C#编译器的代码生成约定,常规业务开发中不会有开发者手动为自定义方法添加
[CompilerGenerated]特性,判断可靠性极高 - 若需要覆盖极端场景(比如用户仅重写了
Equals(object?)或GetHashCode()、未定义强类型Equals方法),可以在判断逻辑中追加对这两个方法的[CompilerGenerated]特性检查,只要任意一个相等相关方法没有该标记,就判定为存在自定义实现 - 该方案支持所有.NET 5及以上版本(Record类型从.NET 5开始正式引入)
内容的提问来源于stack exchange,提问作者Julien Barrau
相关产品推荐
相关产品推荐

