Skip to main content

How to Resolve Error "CS0070: The event 'event' can only appear on the left hand side of += or -=" in C#

The Compiler Error CS0070 is an encapsulation error. The message reads: "The event 'Name' can only appear on the left hand side of += or -= (except when used from within the type 'Owner')".

In C#, Events are designed to be safe. Outside of the class that declared them, external objects are only allowed to subscribe (+=) or unsubscribe (-=). External objects are not allowed to:

  1. Invoke the event (trigger it).
  2. Reset the event (set it to null).
  3. Assign the event directly (using =).

This restriction ensures that one external object cannot accidentally wipe out all other subscribers or falsely trigger an event it doesn't own.

This guide explains how to safely trigger events and handle them across classes.

Understanding Event Encapsulation

An event keyword wraps a delegate. It exposes only the "add" and "remove" permissions to the public.

  • Public: +=, -=
  • Private (Owner only): (), =, = null

If you are in Class A and you try to invoke an event belonging to Class B, the compiler throws CS0070 to stop you from impersonating Class B.

Scenario 1: Trying to Raise an Event from Outside

This is the most common cause. You have a button or a process, and you want to force it to click or finish from your Main method.

Example of Error

using System;

public class Publisher
{
public event EventHandler SomethingHappened;
}

public class Program
{
static void Main()
{
Publisher p = new Publisher();

// ⛔️ Error CS0070: The event 'SomethingHappened' can only appear on the left hand side of += or -=
// You cannot 'call' the event from here. Only the 'Publisher' class can do that.
p.SomethingHappened(p, EventArgs.Empty);
}
}

Solution: Public Trigger Method

If you genuinely need to trigger the event externally, the owning class must provide a public method to do so.

public class Publisher
{
public event EventHandler SomethingHappened;

// ✅ Correct: A public method that the outside world can call.
// This method effectively says "Please raise the event for me."
public void TriggerEvent()
{
SomethingHappened?.Invoke(this, EventArgs.Empty);
}
}

public class Program
{
static void Main()
{
Publisher p = new Publisher();

// We define a subscriber just to see the output
p.SomethingHappened += (sender, e) => Console.WriteLine("Event Received!");

// ✅ Correct: Call the method, not the event directly
p.TriggerEvent();
}
}

Output:

Event Received!

Scenario 2: Trying to Reset an Event from Outside

Sometimes developers try to "clear" all subscribers from an event by setting it to null. This is forbidden because it would disconnect unrelated parts of the system that subscribed to that event without them knowing.

Example of Error

public class DataStream
{
public event EventHandler DataReceived;
}

public class Consumer
{
public void ResetStream(DataStream stream)
{
// ⛔️ Error CS0070: You cannot assign '=' directly.
// This would wipe out ALL subscribers, not just this consumer.
stream.DataReceived = null;
}
}

Solution: Unsubscribe Yourself

You should only be responsible for removing your own subscription.

public class Consumer
{
private void OnData(object sender, EventArgs e) { /*...*/ }

public void StopListening(DataStream stream)
{
// ✅ Correct: Use '-=' to remove specific listeners
stream.DataReceived -= OnData;
}
}

Scenario 3: Derived Classes (The 'OnEvent' Pattern)

A Child Class inherits the event from the Parent Class, but it cannot invoke the event directly. Even though it inherits the member, the "invoke" permission is technically private to the definition level (unless specific accessors are used).

Example of Error

using System;

public class Parent
{
public event EventHandler StateChanged;
}

public class Child : Parent
{
public void ChangeState()
{
// ⛔️ Error CS0070: Even though I am a child, I cannot invoke the parent's event directly.
StateChanged(this, EventArgs.Empty);
}
}

Solution: Protected Virtual Method

The standard .NET pattern is to create a protected virtual method (usually named OnEventName) in the parent class. This allows children to raise the event indirectly.

using System;

public class Parent
{
public event EventHandler StateChanged;

// ✅ Correct: Allow derived classes to raise the event
protected virtual void OnStateChanged(EventArgs e)
{
StateChanged?.Invoke(this, e);
}
}

public class Child : Parent
{
public void ChangeState()
{
Console.WriteLine("Child changing state...");
// ✅ Correct: Call the protected method
base.OnStateChanged(EventArgs.Empty);
}
}
note

This OnEventName pattern is used throughout the .NET Framework (e.g., OnClick in Windows Forms or OnPropertyChanged in MVVM).

Conclusion

CS0070 protects the integrity of the Observer pattern. It ensures that only the object generating the information can broadcast it.

  1. Invocation: If you need to raise an event from outside, create a public void RaiseEvent() method in the owner class.
  2. Inheritance: If a child class needs to raise a parent's event, use a protected virtual void OnEvent() method in the parent.
  3. Assignment: Never try to set an event to null or assign it with =. Always use += to subscribe and -= to unsubscribe.