c# - Throwing exceptions from attribute constructor

淺唱寂寞╮ 提交于 2019-12-23 08:53:46

问题


I found this article on the subject and tried the following:

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

And in unit test project I have the following:

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; }
    }
}

When I run the test, it succeeds. So, the questions are:

  1. Why it does not fail?
  2. Is it really a bad idea to throw exceptions from attributes? Because I think I need to.

Some environment info (just in case it's relevant):

  • Unit tests are run via ReSharper's unit test runner (R# v8.2.0.2160)
  • Visual studio v11.0.61030.0

回答1:


Since attributes are part of class definition available to you at runtime (it's also called "metadata" in geekspeak) CLR does not instantiate them unless some part of your program asks for them. This makes sense: why bother spending CPU cycles for something that nobody wants to access?

Because of this, the execution of the constructor will never happen unless you ask for that attribute.

Here is one way to ask for an attribute that would make your program fail:

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

This code makes CLR instantiate the FailerAttr, which triggers the exception.

Demo on ideone.

If you do not know the type of the attribute, you can retrieve all attributes at once with this call:

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

This causes an exception as well (demo).




回答2:


Attributes are not converted to executable code, they're converted to metadata.

Metadata like this is not used during normal execution, it is only if you start using the metadata, like through reflection, that the attribute type comes back into play.

The constructor or any of the code in the attribute is not executed during compilation. Instead the type and the parameters to the constructor is serialized into the metadata, and only upon inspection using reflection will the constructor actually be executed.

In other words, if you intend this to fail at compile time then you can't.

Try looking for the attributes using reflection, depending on the attribute object is deserialized from the metadata, the constructor may or may not be invoked, but it will definitely not be invoked by just applying it to identifiers.



来源:https://stackoverflow.com/questions/24576695/c-sharp-throwing-exceptions-from-attribute-constructor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!