Skip to main content

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:

  1. Auto-Implemented: { get; set; } (The compiler creates the storage field for you).
  2. 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;
}
}
note

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."

  1. Check Consistency: If you write { get { ... } ... }, you must write { set { ... } }. You cannot mix manual logic with auto-properties ;.
  2. Check Abstract: If you don't want to write a body at all, ensure the property is marked abstract.
  3. Check Version: If using { get; } read-only properties, ensure you are using C# 6.0 or newer.