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

C#:不修改原有属性,用有序列表替代反射访问类属性

替代反射访问遗留类属性的优化方案

针对你提到的遗留MyObj类,既要保留原有Pro1至Pro8属性的兼容性,又要实现列表式索引访问,这里提供几种比switch-case更优的方案:

方案1:手动委托索引器(性能最优)

直接在MyObj类中添加索引器,通过预定义的委托数组映射属性的get/set操作,完全避免反射,性能接近直接访问属性:

public class MyObj
{
    // 原有属性保留不动,兼容系统其他依赖
    public string Pro1 { get; set; }
    public string Pro2 { get; set; }
    public string Pro3 { get; set; }
    public string Pro4 { get; set; }
    public string Pro5 { get; set; }
    public string Pro6 { get; set; }
    public string Pro7 { get; set; }
    public string Pro8 { get; set; }

    // 实现列表式索引访问
    public string this[int index]
    {
        get
        {
            if (index < 0 || index >= _getters.Length)
                throw new ArgumentOutOfRangeException(nameof(index));
            return _getters[index]();
        }
        set
        {
            if (index < 0 || index >= _setters.Length)
                throw new ArgumentOutOfRangeException(nameof(index));
            _setters[index](value);
        }
    }

    // 预初始化属性访问委托数组
    private readonly Func<string>[] _getters;
    private readonly Action<string>[] _setters;

    public MyObj()
    {
        _getters = new Func<string>[]
        {
            () => Pro1, () => Pro2, () => Pro3, () => Pro4,
            () => Pro5, () => Pro6, () => Pro7, () => Pro8
        };

        _setters = new Action<string>[]
        {
            val => Pro1 = val, val => Pro2 = val, val => Pro3 = val, val => Pro4 = val,
            val => Pro5 = val, val => Pro6 = val, val => Pro7 = val, val => Pro8 = val
        };
    }
}

使用方式:

var obj = new MyObj();
obj[0] = "赋值给Pro1"; // 对应Pro1
var pro4Value = obj[3]; // 获取Pro4的值

方案2:表达式树预编译(适配属性扩展场景)

如果后续可能新增Pro9这类属性,手动维护委托数组太麻烦,可以用表达式树在静态构造中一次性生成委托,仅在类首次加载时做一次反射操作,后续访问无反射开销:

public class MyObj
{
    // 原有属性保留不动
    public string Pro1 { get; set; }
    public string Pro2 { get; set; }
    public string Pro3 { get; set; }
    public string Pro4 { get; set; }
    public string Pro5 { get; set; }
    public string Pro6 { get; set; }
    public string Pro7 { get; set; }
    public string Pro8 { get; set; }

    public string this[int index]
    {
        get => _getters[index](this);
        set => _setters[index](this, value);
    }

    private static readonly Func<MyObj, string>[] _getters;
    private static readonly Action<MyObj, string>[] _setters;

    static MyObj()
    {
        // 自动按规则筛选并排序Pro属性
        var properties = typeof(MyObj)
            .GetProperties(BindingFlags.Public | BindingFlags.Instance)
            .Where(p => p.Name.StartsWith("Pro") && int.TryParse(p.Name.Substring(3), out _))
            .OrderBy(p => int.Parse(p.Name.Substring(3)))
            .ToArray();

        // 生成get委托
        _getters = properties.Select(p =>
        {
            var param = Expression.Parameter(typeof(MyObj));
            var propertyAccess = Expression.Property(param, p);
            return Expression.Lambda<Func<MyObj, string>>(propertyAccess, param).Compile();
        }).ToArray();

        // 生成set委托
        _setters = properties.Select(p =>
        {
            var objParam = Expression.Parameter(typeof(MyObj));
            var valueParam = Expression.Parameter(typeof(string));
            var propertyAccess = Expression.Property(objParam, p);
            var assign = Expression.Assign(propertyAccess, valueParam);
            return Expression.Lambda<Action<MyObj, string>>(assign, objParam, valueParam).Compile();
        }).ToArray();
    }
}

方案3:包装类(不修改原类场景)

如果无法修改MyObj类(比如类是密封的或属于第三方库),可以写一个包装类实现列表式访问:

public class MyObjListWrapper
{
    private readonly MyObj _target;

    public MyObjListWrapper(MyObj target)
    {
        _target = target ?? throw new ArgumentNullException(nameof(target));
    }

    public string this[int index]
    {
        get => _getters[index](_target);
        set => _setters[index](_target, value);
    }

    private static readonly Func<MyObj, string>[] _getters = new[]
    {
        obj => obj.Pro1, obj => obj.Pro2, obj => obj.Pro3, obj => obj.Pro4,
        obj => obj.Pro5, obj => obj.Pro6, obj => obj.Pro7, obj => obj.Pro8
    };

    private static readonly Action<MyObj, string>[] _setters = new[]
    {
        (obj, val) => obj.Pro1 = val, (obj, val) => obj.Pro2 = val,
        (obj, val) => obj.Pro3 = val, (obj, val) => obj.Pro4 = val,
        (obj, val) => obj.Pro5 = val, (obj, val) => obj.Pro6 = val,
        (obj, val) => obj.Pro7 = val, (obj, val) => obj.Pro8 = val
    };
}

使用方式:

var obj = new MyObj();
var wrapper = new MyObjListWrapper(obj);
wrapper[0] = "赋值给Pro1";

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 22:40:35