How to Resolve Error "CS0840: Property must declare a body because it is not marked abstract or extern" in C#
The Compiler Error CS0840 is a syntax error regarding Properties. The message reads: "'PropertyName' must declare a body because it is not marked abstract or extern. Automatically implemented properties must define both get and set accessors."
In C#, a property can be implemented in two main ways:
- Auto-Implemented:
{ get; set; }(The compiler creates the storage field for you). - Manually Implemented:
{ get { return ... } set { ... } }(You write the logic).
CS0840 occurs when you try to create a "Hybrid" property (manually implementing one accessor but trying to auto-implement the other), or when you define a property that looks like an abstract declaration inside a non-abstract class.
Understanding Property Syntax
To satisfy the compiler, a property must fall into one of these strict categories:
- Full Auto-Property: Both accessors have semicolons.
public int X { get; set; }
- Full Manual Property: Both accessors have bodies.
public int X { get { return 0; } set { } }
- Abstract Property: No bodies, marked
abstract.public abstract int X { get; set; }
You cannot mix and match styles within a single property.
Scenario 1: Mixing Manual and Auto Accessors (The Hybrid Error)
This is the most common cause in modern C#. You want custom logic for the get accessor (to calculate a value), but you want the set accessor to just store the value automatically. C# does not support this partial automation. If you define a body for one, you must define a body for the other.
Example of error
Attempting to manually implement get while using auto-syntax for set.
public class User
{
private string _name;
// ⛔️ Error CS0840: 'Name' must declare a body because it is not marked abstract or extern.
// You defined a body for 'get', so 'set' cannot be auto-implemented with ';'.
public string Name
{
get { return _name ?? "Unknown"; }
set;
}
}
Solution: Use a Backing Field
You must manually implement the setter and store the value in a private backing field.
public class User
{
private string _name;
public string Name
{
// ✅ Correct: Both accessors are manually implemented.
get { return _name ?? "Unknown"; }
set { _name = value; }
}
}
Scenario 2: Intending to make an Abstract Property
Sometimes you declare a property using the short syntax { get; set; } intending for derived classes to implement it, but you forget to mark the property (or the class) as abstract. While { get; set; } is valid as an auto-property, if you use { get; } (read-only) without initializing it, or in older versions of C#, the compiler might interpret this as an incomplete definition.
More specifically, if you mistakenly use the extern syntax style without the keyword, this error appears.
Example of error
Defining a property that looks like a contract (interface style) inside a standard class.
public class BaseEntity
{
// ⛔️ Error CS0840: The compiler thinks you want an auto-prop,
// but in some contexts (or if you wanted it abstract), this is ambiguous.
// If you wanted this to be abstract, you forgot the keyword.
public int Id { get; set; }
// Note: In modern C#, { get; set; } is valid as an auto-prop.
// But if you meant "I will define this elsewhere", you need abstract.
}
Solution: Add abstract
If the class is meant to be a base class and holds no data itself, mark it abstract.
// ✅ Correct: The class is abstract
public abstract class BaseEntity
{
// ✅ Correct: The property is abstract.
// This tells the compiler: "No body needed here, children will provide it."
public abstract int Id { get; set; }
}
Scenario 3: Legacy C# Versions (Read-Only Auto-Props)
If you are working on a very old project (using C# 5.0 or earlier, targeted at .NET Framework 4.5 or older), Read-Only Auto-Properties ({ get; }) were not yet supported.
Example of error (In C# 5.0)
public class Config
{
// ⛔️ Error CS0840 (Only in old compilers):
// Auto-implemented properties must define both get and set accessors.
public int MaxUsers { get; }
}
Solution: Private Set
In older versions, you must provide a private set to satisfy the syntax requirement.
public class Config
{
// ✅ Correct (Legacy Compatible): Add a private setter.
public int MaxUsers { get; private set; }
public Config()
{
MaxUsers = 100;
}
}
In C# 6.0+ (Modern .NET), public int MaxUsers { get; } is perfectly valid. If you see this error with this syntax, check your project's LangVersion setting.
Conclusion
CS0840 ensures you don't write "half-properties."
- Check Consistency: If you write
{ get { ... } ... }, you must write{ set { ... } }. You cannot mix manual logic with auto-properties;. - Check Abstract: If you don't want to write a body at all, ensure the property is marked
abstract. - Check Version: If using
{ get; }read-only properties, ensure you are using C# 6.0 or newer.