C#CustomAttribute的奇怪行为

时间:2018-01-28 06:45:20

标签: c# reflection custom-attributes

在我的应用程序中,我遇到了一个我无法理解的CustomAttributes和Reflection的奇怪情况,我试图减少问题。假设我有以下自定义属性:

class A : Attribute
{
    public virtual string SayHi()
    {
        return "Hi From A";
    }
}
class B : A
{
    public override string SayHi()
    {
        return "Hi From B";
    }
}

以下课程使用自定义属性进行修饰:

[A]
class X
{ }

[B]
class Y
{ }

在下面的方法中,我映射用" A"装饰的每种类型的类。属性为返回其自定义属性返回的值的函数:

static Dictionary<Type, Func<string>> dic = new Dictionary<Type, Func<string>>();
static void func()
{
    A attr;
    foreach (var type in typeof(Program).Assembly.GetTypes())
    {
        var attrs = type.GetCustomAttributes(typeof(A)).ToList();
        if(attrs.Any())
        {
            attr = attrs.First() as A;
            dic.Add(type, () => attr.SayHi());
        }
    }
}

映射到X类型的函数可能返回&#34; Hi来自A&#34;但奇怪的是,以下代码打印出来&#34; Hi来自B&#34;到控制台!

func();
Console.WriteLine(dic[typeof(X)]());

我错过了语言功能吗?

1 个答案:

答案 0 :(得分:1)

此行为与属性无关。这是一个经典的“捕获变量”问题。你在attr循环之外声明foreach变量,然后在委托中引用它,所以字典中的每个函数最终都会引用{{1}的最后一个值。在通过attr

之后结束

更简单的复制如下:

foreach

输出:

int x;
var actions = new List<Action>();
for (int i = 0; i < 3; i++)
{
    x = i;
    actions.Add(() => Console.WriteLine(x));
}
foreach (var action in actions)
{
    action();
}

如果您将声明移动到循环中,您将获得您正在寻找的行为。

2
2
2