You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#如何通过反射区分record类型中的init访问器与set访问器

反射区分C# positional record的init与set访问器方法

核心原理

positional record的位置参数生成的属性默认带init访问器,IL层面会在setter方法上标记System.Runtime.CompilerServices.IsExternalInit必填修饰符,通过反射检查该修饰符即可区分init和普通set访问器。

实现代码

using System.Reflection;
using System.Runtime.CompilerServices;

/// <summary>
/// 判断属性是否为init-only属性
/// </summary>
public static bool IsInitOnlyProperty(PropertyInfo propertyInfo)
{
    MethodInfo? setMethod = propertyInfo.GetSetMethod();
    // 无set访问器,属于纯get只读属性
    if (setMethod == null)
        return false;
    // 检查set方法的必填自定义修饰符是否包含IsExternalInit标记
    return setMethod.ReturnParameter
        .GetRequiredCustomModifiers()
        .Contains(typeof(IsExternalInit));
}

使用示例

// 测试用positional record
record MyRecord(int MyProperty);
// 测试用带普通set的类
class NormalClass
{
    public int MyProperty { get; set; }
}

// 验证效果
var recordProp = typeof(MyRecord).GetProperty(nameof(MyRecord.MyProperty))!;
Console.WriteLine(IsInitOnlyProperty(recordProp)); // 输出 True,确认是init访问器

var classProp = typeof(NormalClass).GetProperty(nameof(NormalClass.MyProperty))!;
Console.WriteLine(IsInitOnlyProperty(classProp)); // 输出 False,确认是普通set访问器

不可写属性判断逻辑

如果需要判断属性是否为构造完成后不可修改的属性,可直接使用以下判断条件:

bool isRuntimeReadOnly = pi.GetSetMethod() == null || IsInitOnlyProperty(pi);

该条件对纯get属性、init属性都会返回True,完全匹配你对positional record属性不可写的判断需求。

内容的提问来源于stack exchange,提问作者Carl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 02:24:04