How to Resolve Error "CS0836: Cannot use anonymous type in a constant expression" in C#
The Compiler Error CS0836 is a limitation regarding Compile-Time Constants. The message reads: "Cannot use anonymous type in a constant expression".
In C#, a constant expression is an expression that can be fully evaluated by the compiler at build time. This allows the value to be embedded directly into the compiled metadata (DLL).
- Constants support: numbers, strings, null, and booleans.
- Anonymous Types (
new { A = 1 }): imply Object Instantiation (memory allocation on the heap).
Because object creation happens at Runtime (when the program is running), the compiler cannot "bake" an anonymous object into a constant slot.
This guide explains where this conflict occurs and how to switch to runtime initialization.
Understanding Compile-Time vs. Runtime
const: "I know exactly what these bytes are right now, before the program runs."new { ... }: "Please ask the Operating System for memory and build this object structure when the code executes."
These two concepts are mutually exclusive. You cannot ask the compiler to freeze a dynamic memory allocation into a static file.
Scenario 1: Declaring const Fields
This is the most direct cause. You try to create a "constant" configuration object using anonymous type syntax.
Example of error
Attempting to assign an anonymous object to a const field.
public class Config
{
// ⛔️ Error CS0836: Cannot use anonymous type in a constant expression.
// 1. 'const' requires a compile-time value.
// 2. 'new { ... }' is a runtime object creation.
public const object DefaultSettings = new { Theme = "Dark", Version = 1 };
}
Solution: Use static readonly
If you need a globally available, immutable object, use static readonly. This allows the initialization to happen at Runtime (when the class loads), satisfying the need for object creation.
public class Config
{
// ✅ Correct: 'static readonly' allows runtime initialization via 'new'.
// Note: We use 'object' or 'dynamic' because anonymous types cannot be
// returned as strongly-typed public fields easily.
public static readonly object DefaultSettings = new { Theme = "Dark", Version = 1 };
}
Scenario 2: Default Parameter Values
In C#, optional parameters must have a constant default value. You cannot use an anonymous type as a default value for a method parameter.
Example of error
public class Logger
{
// ⛔️ Error CS0836: The default value for 'context' must be a compile-time constant.
public void Log(string message, object context = new { Id = 0 })
{
// ...
}
}
Solution: Use null and Handle Inside
Set the default value to null, and then assign the anonymous object inside the method body if the value is missing.
public class Logger
{
// ✅ Correct: 'null' is a valid constant.
public void Log(string message, object context = null)
{
// Initialize if null
if (context == null)
{
context = new { Id = 0 };
}
Console.WriteLine($"Msg: {message}, Context: {context}");
}
}
Scenario 3: Attribute Arguments
Attributes ([MyAttribute]) are metadata baked into the assembly. Their arguments must be constant expressions. You cannot pass an anonymous object (or any object created with new) to an attribute constructor.
Example of error
public class MetadataAttribute : Attribute
{
public object Data { get; }
public MetadataAttribute(object data) => Data = data;
}
// ⛔️ Error CS0836: Attribute arguments must be constants.
// You cannot bake a heap object into metadata.
[Metadata(new { Author = "Alice" })]
public class MyClass
{
}
Solution: Pass Primitives or Strings
Attributes simply cannot accept complex objects. You must pass the data as individual primitive arguments (strings, ints, bools) or use a serialized string (JSON).
public class MetadataAttribute : Attribute
{
public string Author { get; }
// Accept primitives
public MetadataAttribute(string author) => Author = author;
}
// ✅ Correct: "Alice" is a constant string literal.
[Metadata("Alice")]
public class MyClass
{
}
Conclusion
CS0836 prevents you from treating dynamic memory allocations as static data.
- Check
const: If declaring a field, switchconsttostatic readonly. - Check Parameters: If defining optional parameters, default to
nulland instantiate the anonymous type inside the method. - Check Attributes: You cannot pass objects to attributes. Pass Strings or Primitives instead.