Skip to main content

How to Resolve Error "CS0073: An add or remove accessor must have a body" in C#

The Compiler Error CS0073 is a syntax error regarding Event declarations. The message reads: "An add or remove accessor must have a body".

In C#, events usually fall into two categories:

  1. Field-like events: You let the compiler handle the storage and subscription logic automatically.
  2. Custom events: You explicitly define how subscribers are added (add) and removed (remove).

This error occurs when you try to mix these syntaxes. Specifically, if you declare add and remove keywords, you must provide the implementation code block (the "body") inside curly braces { }. You cannot end them with a semicolon ; unless the event is marked abstract.

This guide explains how to fix this syntax error depending on your intent.

Understanding the Syntax Mismatch

When you define a property or event, a semicolon ; usually means "automatic" or "abstract," while curly braces { ... } mean "here is the code."

If you explicitly write the word add, the compiler expects you to immediately follow it with the code to execute when a user subscribes. Putting a semicolon there is like writing a method void DoWork(); inside a normal class—the compiler asks, "Where is the code for this method?"

Scenario: The Invalid "Half-Definition"

This error often happens when developers try to declare an event but use property-style syntax incorrectly, or when they are converting an auto-property to a full property but forget the body.

Example of error:

using System;

public class Button
{
// ⛔️ Error CS0073: An add or remove accessor must have a body
// The compiler sees 'add', so it expects implementation logic { ... },
// but it found a semicolon ';' instead.
public event EventHandler Click
{
add;
remove;
}
}

Solution 1: Use Field-Like Syntax (Auto-Implemented)

If you do not need custom logic (like logging subscribers or forwarding events), you should use the Field-like Event syntax. This is the standard way to define events in C#.

Delete the add and remove blocks entirely and end the event declaration with a semicolon.

using System;

public class Button
{
// ✅ Correct: The compiler automatically generates a private backing field
// and the default add/remove logic for you.
public event EventHandler Click;
}

Solution 2: Provide the Body (Custom Implementation)

If you do need custom logic (for example, to use a thread-safe collection or valid explicit interface implementation), you must provide the { } blocks and write the code yourself.

Note that when you do this, the compiler stops generating the private backing field, so you must declare one manually.

using System;

public class Button
{
// 1. Create a private backing field
private EventHandler _click;

// 2. Define the public event with custom accessors
public event EventHandler Click
{
// ✅ Correct: The 'add' accessor has a body { ... }
add
{
Console.WriteLine("Someone subscribed!");
_click += value; // 'value' is the incoming delegate
}

// ✅ Correct: The 'remove' accessor has a body { ... }
remove
{
Console.WriteLine("Someone unsubscribed!");
_click -= value;
}
}
}

Solution 3: Abstract Events

If your intention was to define an event in a base class that derived classes must implement, you should use the abstract keyword. Only abstract members allow accessors without bodies.

using System;

public abstract class BaseControl
{
// ✅ Correct: Abstract events do not have bodies.
// Derived classes will be forced to implement this.
public abstract event EventHandler Click;
}

Conclusion

CS0073 indicates incomplete code.

  1. If you want standard behavior: Delete the add/remove lines and simply end the declaration with ; (e.g., public event EventHandler MyEvent;).
  2. If you want custom logic: Add curly braces { ... } after add and remove and write the implementation code.
  3. If you want inheritance enforcement: Add the abstract keyword to the declaration.