【问题标题】:c# - Throwing exceptions from attribute constructorc# - 从属性构造函数中抛出异常
【发布时间】:2014-07-04 14:42:04
【问题描述】:

我在该主题上找到了this article,并尝试了以下方法:

public class FailerAttr : Attribute {
    public FailerAttr(string s) {
        throw new Exception("I should definitely fail!");
    }
}

在单元测试项目中,我有以下内容:

using Microsoft.VisualStudio.TestTools.UnitTesting;

[TestClass]
public class Test {
    [TestMethod]
    public void GoFail() {
        // Make sure attribute will get initialized
        new Failer();
    }

    private class Failer {
        [FailerAttr("")]
        public int Prop { get; set; }
    }
}

当我运行测试时,它成功了。所以,问题是:

  1. 为什么它没有失败?
  2. 从属性中抛出异常真的是个坏主意吗?因为我认为我需要这样做。

一些环境信息(以防万一):

  • 单元测试通过 ReSharper 的单元测试运行器 (R# v8.2.0.2160) 运行
  • Visual Studio v11.0.61030.0

【问题讨论】:

  • 可以用反射获取属性吗?
  • @KarelFrajtak 我不确定,我还没试过。将在一分钟内尝试
  • 您的评论// Make sure attribute will get initialized 是错误的。只有在检查属性时才会构造它(通常通过反射)。
  • @Bun 是的,你是对的。我想我没有很好地理解属性的概念。

标签: c# exception custom-attributes


【解决方案1】:

由于属性是您在运行时可用的类定义的一部分(在 geekspeak 中也称为“元数据”),除非您的程序的某些部分要求它们,否则 CLR 不会实例化它们。这是有道理的:为什么要为没人想访问的东西花费 CPU 周期?

因此,除非您请求该属性,否则构造函数的执行将永远不会发生。

下面是一种请求属性的方法,该属性会使您的程序失败:

var attr = Attribute.GetCustomAttribute(typeof(Failer).GetProperty("Prop"), typeof(FailerAttr));

此代码使 CLR 实例化 FailerAttr,这会触发异常。

Demo on ideone.

如果您不知道属性的类型,您可以通过此调用一次检索所有属性:

var allAttributes = Attribute.GetCustomAttributes(typeof(Failer).GetProperty("Prop"));

这也会导致异常 (demo)。

【讨论】:

  • 将此标记为关于如何实现失败的代码示例的答案。非常感谢!
  • 不是很相关,但是如果你的目标是.NET 4.5或更高版本,有通用的扩展方法(需要using System.Reflection;),所以你可以说typeof(Failer).GetProperty("Prop").GetCustomAttribute<FailerAttr>()(单或空)或typeof(Failer).GetProperty("Prop").GetCustomAttributes<FailerAttr>() (所有出现,可能为空)。
  • @JeppeStigNielsen 我们正在迁移到 4.5.1,为此我在 4.0 上使用我自己的扩展方法。谢谢建议,不知道这个
【解决方案2】:

属性不会转换为可执行代码,而是转换为元数据。

这样的元数据在正常执行期间不会使用,只有当您开始使用元数据时,例如通过反射,属性类型才会重新发挥作用。

在编译期间不执行构造函数或属性中的任何代码。相反,构造函数的类型和参数被序列化到元数据中,并且只有在使用反射检查时才会实际执行构造函数。

换句话说,如果你打算在编译时失败,那么你不能。

尝试使用反射查找属性,根据属性对象从元数据中反序列化,构造函数可能会或可能不会被调用,但绝对不会通过将其应用于标识符来调用。

【讨论】:

  • 那么当通过反射获取属性时,构造函数代码是否运行(或依赖),例如使用typeof(Failer).GetProperty("Prop").GetCustomAttributes() 或类似的?
  • 它在你使用那条反射时执行,而不是在编译时执行。
猜你喜欢
  • 2019-03-11
  • 2023-03-11
  • 2011-11-04
  • 2014-11-03
  • 1970-01-01
  • 1970-01-01
  • 2017-02-09
  • 2018-05-21
  • 2010-10-29
相关资源
最近更新 更多