How to Resolve Error "CS0079: The event 'event' can only appear on the left hand side of += or -=" in C#
The Compiler Error CS0079 is a syntax error that occurs when you try to access an Event as if it were a variable (a delegate field), but the event does not have a backing field associated with its name.
This error looks very similar to CS0070, but there is a key distinction:
- CS0070 happens when you try to invoke an event from outside the class (permission issue).
- CS0079 typically happens when you try to invoke an event from inside the class, but the event was declared with Custom Accessors (
add/remove).
When you define custom accessors, the compiler stops generating the default private delegate field. Consequently, the name MyEvent no longer refers to a "thing" that holds data; it refers strictly to the subscription mechanism. You cannot "invoke" a mechanism directly; you can only subscribe (+=) or unsubscribe (-=) to it.
This guide explains how to properly manage and invoke events with custom accessors.
Understanding Field-Like vs. Custom Events
To understand this error, you must understand what the compiler generates for you.
1. Field-Like Event (Standard):
public event EventHandler MyEvent;
- Compiler Creates: A private delegate field (also named
MyEvent) AND publicadd/removemethods. - Inside the class: Using
MyEventrefers to the private field. You can invoke it (MyEvent()) or check it (MyEvent != null).
2. Custom Event:
public event EventHandler MyEvent { add { ... } remove { ... } }
- Compiler Creates: ONLY the
add/removemethods. No field is created. - Inside the class: Using
MyEventrefers to the property group. You cannot "run" a property group. Attempting to writeMyEvent()causes CS0079 because there is no delegate field with that name to execute.
Scenario 1: Invoking an Event with Custom Accessors
When you implement manual add and remove logic, you are responsible for storing the subscribers yourself (usually in a private field). When you want to raise the event, you must invoke that private field, not the public event name.
Example of error
using System;
public class Button
{
// A custom event implementation
public event EventHandler Clicked
{
add { Console.WriteLine("Added"); }
remove { Console.WriteLine("Removed"); }
}
public void Press()
{
// ⛔️ Error CS0079: The event 'Clicked' can only appear on the left hand side of += or -=
// 'Clicked' is just a name for the add/remove methods. It holds no data.
// There is no backing field named 'Clicked' to invoke.
Clicked(this, EventArgs.Empty);
}
}
Solution: Use a Backing Field
You must declare a private delegate field to store the subscribers, and invoke that field.
using System;
public class Button
{
// 1. Create a private field to hold the delegates
private EventHandler _clickedSubscribers;
// 2. Define the public event using the field
public event EventHandler Clicked
{
add
{
_clickedSubscribers += value;
}
remove
{
_clickedSubscribers -= value;
}
}
public void Press()
{
// ✅ Correct: Invoke the private field, not the public event name
_clickedSubscribers?.Invoke(this, EventArgs.Empty);
}
}
Scenario 2: Checking if the Event is Null
Similarly, you might try to check if anyone is subscribed to the event by comparing it to null. If you are using custom accessors, the name of the event cannot be read as a value.
Example of error
public class DataStream
{
public event EventHandler DataReady
{
add { }
remove { }
}
public void CheckListeners()
{
// ⛔️ Error CS0079: Cannot read value of 'DataReady'
if (DataReady != null)
{
// ...
}
}
}
Solution
Again, check the backing field you created.
public class DataStream
{
private EventHandler _dataReadyBacking;
public event EventHandler DataReady
{
add { _dataReadyBacking += value; }
remove { _dataReadyBacking -= value; }
}
public void CheckListeners()
{
// ✅ Correct: Check the private field
if (_dataReadyBacking != null)
{
Console.WriteLine("We have listeners.");
}
}
}
Conclusion
CS0079 means you are trying to use an event definition as if it were a variable, but no variable exists for that name.
- Check Declarations: Did you add
{ add { } remove { } }to your event? - Use Backing Fields: If yes, you must manually create a
privatefield to store the delegates. - Invoke the Field: Update your code to invoke (or check) the private field (
_myEvent) instead of the public event name (MyEvent).