Middle · Trace · Attribute data versus attribute execution

Trace the metadata value and constructor counter before and after live attribute retrieval.

Think through your answer before opening the explanation.

Runtime & concurrency

using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Reflection;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;

var data = CustomAttributeData.GetCustomAttributes(typeof(Annotated)).Single(item => item.AttributeType == typeof(MarkerAttribute));
Console.WriteLine($"data:{data.ConstructorArguments[0].Value}");
Console.WriteLine($"constructors:{MarkerAttribute.Created}");
var instance = (MarkerAttribute)Attribute.GetCustomAttribute(typeof(Annotated), typeof(MarkerAttribute))!;
Console.WriteLine($"instance:{instance.Name}");
Console.WriteLine($"constructors:{MarkerAttribute.Created}");
[Marker("demo")] sealed class Annotated { }
[AttributeUsage(AttributeTargets.Class)]
sealed class MarkerAttribute : Attribute
{
    public static int Created;
    public string Name { get; }
    public MarkerAttribute(string name) { Name = name; Created++; }
}
Reveal answer and reasoning

The lines are data:demo, constructors:0, instance:demo, and constructors:1. The first query selects MarkerAttribute's recorded data and reads the literal demo argument without constructing a MarkerAttribute. Accessing the counter then reports its unchanged zero. The live retrieval invokes the constructor, which stores Name and increments Created once, making the final two observations demo and one.

The annotation does not instantiate the annotated class or modify it, and reading its Type does not authorize treating every attribute reader as passive. The counter is a deliberate teaching side effect, not an application policy. A common wrong trace increments it during metadata inspection or claims the annotation must have run during class loading. The explicit API distinction explains the result without relying on metadata enumeration order, because the query filters the exact custom attribute type before selecting its constructor argument.

What a strong answer covers

  • CustomAttributeData reads demo without construction.
  • The counter remains zero until instance retrieval.
  • The final count is one in this fresh execution.

Common pitfall

Counting a metadata read as an executed custom attribute constructor.

Follow-up questions

  1. What would a second live retrieval need you to observe?
  2. Why does the query filter AttributeType?

Self-review

Choose what to revisit. These marks are your own assessment and are separate from lesson completion.

Primary references

Open lesson and code ↗

← All interview questions