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

C#自定义属性与反射的异常行为技术咨询

问题分析与解决方案

你遇到的这个问题其实是C#里闭包的一个常见“陷阱”——闭包捕获的是变量的引用,而不是迭代时的变量值,这也是你忽略的核心语言特性。

问题根源

在你的func方法中,attr是在循环外部声明的变量:

A attr;
foreach (var type in typeof(Program).Assembly.GetTypes()) {
    // ...
    attr = attrs.First() as A;
    dic.Add(type, () => attr.SayHi());
}

你创建的lambda表达式() => attr.SayHi()并没有捕获当前迭代中attr的具体值,而是捕获了attr这个变量本身的引用。当循环结束时,attr最终指向的是最后一个被处理的属性实例(也就是类Y上的B属性)。所以当你后续调用dic[typeof(X)]()时,lambda会使用attr的最终值,自然返回"Hi From B"。

修复方案

解决方法很简单:在循环内部声明一个局部变量,把当前迭代的属性实例赋值给这个局部变量,让闭包捕获这个局部变量(每个迭代的局部变量都是独立的,持有当前迭代的属性值):

static Dictionary<Type, Func<string>> dic = new Dictionary<Type, Func<string>>();
static void func() {
    foreach (var type in typeof(Program).Assembly.GetTypes()) {
        var attrs = type.GetCustomAttributes(typeof(A)).ToList();
        if(attrs.Any()) {
            // 循环内声明局部变量,保存当前迭代的属性实例
            var currentAttr = attrs.First() as A;
            dic.Add(type, () => currentAttr.SayHi());
        }
    }
}

修改后,再次执行代码:

func();
Console.WriteLine(dic[typeof(X)]()); // 输出 "Hi From A"
Console.WriteLine(dic[typeof(Y)]()); // 输出 "Hi From B"

就能得到符合预期的结果了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:44:57