When is it run? Does it run for each object to which I apply it, or just once? Can it do anything, or its actions are restricted?
4 Answers
When is the constructor run? Try it out with a sample:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Creating MyClass instance");
MyClass mc = new MyClass();
Console.WriteLine("Setting value in MyClass instance");
mc.Value = 1;
Console.WriteLine("Getting attributes for MyClass type");
object[] attributes = typeof(MyClass).GetCustomAttributes(true);
}
}
[AttributeUsage(AttributeTargets.All)]
public class MyAttribute : Attribute
{
public MyAttribute()
{
Console.WriteLine("Running constructor");
}
}
[MyAttribute]
class MyClass
{
public int Value { get; set; }
}
And what is the output?
Creating MyClass instance
Setting value in MyClass instance
Getting attributes for MyClass type
Running constructor
So, the attribute constructor is run when we start to examine the attribute. Note that the attribute is fetched from the type, not the instance of the type.

- 155,851
- 29
- 291
- 343
-
20Note that the constructor is run multiple times if you call GetCustomAttributes multiple times. – Wim Coenen Jul 22 '09 at 22:20
-
1Yes, that is good to point out; there is no caching going on for the attributes (as opposed to the Type objects that, as far as I recall, are cached while the application is running). – Fredrik Mörk Jul 22 '09 at 22:24
-
Anyone know _why_ the attribute objects aren't cached? – Matt Howells Jul 22 '09 at 22:53
-
@Matt: I don't know, but my guess would be that Type object are used frequently enough to make it interesting to make the investment of caching them, while that may not be the case with Attributes. But I am just speculating. – Fredrik Mörk Jul 23 '09 at 14:42
-
3You may also add code in the constructor of your attribute for instance to change values according to the context. if the attribute is cached you can't do that. – Guillaume Mar 10 '10 at 11:22
-
Well... thanks. Burst my bubble a bit, but helpful nonetheless. – StingyJack Jan 03 '12 at 21:22
-
To cache the `CustomAttribute` data for an attribute that is always associated with certain `Type`, define a custom `TypeDelegator` (or a hierarchy of `TypeDelegator` classes that parallels the inheritance hierarchy of your actual classes). `TypeDelegator` is a sensible place to put custom `Type` info since it inherits from `Type`. This extends the respective CLR `Type` instances with additional field, method, and property runtime metadata based on your custom attribute data. Your app then upgrades each `Type` to a cached `TypeDelegator` only once, and then always deals with the latter. – Glenn Slayden Aug 18 '20 at 06:02
The constructor is run every time the GetCustomAttributes
is invoked, or whenever some other code invokes the constructor directly (not that there's a good reason to do so, but it's not impossible either).
Note that at least in .NET 4.0, the attribute instances are not cached; a fresh instance is constructed every time GetCustomAttributes
is called:
[Test]
class Program
{
public static int SomeValue;
[Test]
public static void Main(string[] args)
{
var method = typeof(Program).GetMethod("Main");
var type = typeof(Program);
SomeValue = 1;
Console.WriteLine(method.GetCustomAttributes(false)
.OfType<TestAttribute>().First().SomeValue);
// prints "1"
SomeValue = 2;
Console.WriteLine(method.GetCustomAttributes(false)
.OfType<TestAttribute>().First().SomeValue);
// prints "2"
SomeValue = 3;
Console.WriteLine(type.GetCustomAttributes(false)
.OfType<TestAttribute>().First().SomeValue);
// prints "3"
SomeValue = 4;
Console.WriteLine(type.GetCustomAttributes(false)
.OfType<TestAttribute>().First().SomeValue);
// prints "4"
Console.ReadLine();
}
}
[AttributeUsage(AttributeTargets.All)]
class TestAttribute : Attribute
{
public int SomeValue { get; private set; }
public TestAttribute()
{
SomeValue = Program.SomeValue;
}
}
It is not the best idea to have attributes behave like this, of course. At the very least, note that GetCustomAttributes
is not documented to behave like this; in fact, what happens in the above program is not specified in the documentation.

- 59,298
- 38
- 251
- 324
-
That's the way it was meant to behave (the verb "get" implies action). GetCustomAttributes MUST return fresh copies every time. That's the only way to guarantee the code executed in the constructor of the attribute is examining a relevant context. With dynamic assemblies, interception, and everything else, there's no telling what could have changed since that last call. It may even return a different set of attributes based on a real time setting. – Paul Easter Feb 07 '15 at 08:36
-
1@PaulEaster I do agree that this behaviour is clearly by-design, enabling some interesting attribute constructors. But when I was less experienced with .NET, it seemed intuitive that since attributes are baked into the assembly metadata, they cannot possibly change during program runtime (but it turned out they can). So such constructors can certainly give someone a nasty surprise. – Roman Starkov Feb 07 '15 at 09:28
Set a debugger break-point inside an attribute constructor and write some reflection code that reads those attributes. You'll notice that the attribute objects won't be created until they are returned from the relfection API. Attributes are per class. They are part of the meta data.
Have a look at this:
Program.cs
using System;
using System.Linq;
[My(15)]
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Program started");
var ats =
from a in typeof(Program).GetCustomAttributes(typeof(MyAttribute), true)
let a2 = a as MyAttribute
where a2 != null
select a2;
foreach(var a in ats)
Console.WriteLine(a.Value);
Console.WriteLine("Program ended");
Console.ReadLine();
}
}
MyAttribute.cs
using System;
[AttributeUsage(validOn : AttributeTargets.Class)]
public class MyAttribute : Attribute
{
public MyAttribute(int x)
{
Console.WriteLine("MyAttribute created with {0}.", x);
Value = x;
}
public int Value { get; private set; }
}
Result
Program started
MyAttribute created with 15.
15
Program ended
But don't worry about the performance of attribute constructors. They are the fastest part of reflection :-P

- 4,416
- 3
- 31
- 42
-
Damn! Tried to do this one in VS 2010 but I'm totally lost without ReSharper XD – Christian Klauser Jul 22 '09 at 22:30
The metadata in the executable or DLL stores:
- A metadata token indicating the constructor to call
- The arguments
When I get to that section of my CLI implementation, I plan to lazy-call the constructor the first time GetCustomAttributes()
is called for the ICustomAttributeProvider
. If a particular attribute type is requested, I'll only construct the ones required to return that type.

- 97,721
- 20
- 209
- 280