Skip to main content

How to Resolve Warning "CS0067: The event 'event' is never used" in C#

The Compiler Warning CS0067 indicates dead code or incomplete logic regarding Events. The message reads: "The event 'MyEvent' is never used".

In C#, declaring an event is similar to installing a doorbell. If you install the doorbell (declare the event) but never wire it up so it can ring (never raise/invoke the event), the compiler warns you that the event serves no purpose. Subscribers might listen to it, but they will never be notified.

This guide explains why this warning occurs and how to handle it, especially when implementing interfaces that force you to declare events you don't intend to use.

Understanding the Warning

When you declare a field-like event:

public event EventHandler SomethingChanged;

The C# compiler automatically generates a private backing field to store the list of subscribers (delegates). The warning CS0067 triggers if the compiler sees that code inside the class never accesses this private backing field—specifically, it never invokes the delegate.

This usually means one of two things:

  1. Accidental Omission: You forgot to write the code that triggers the event.
  2. Forced Implementation: You are implementing an Interface that requires the event, but your specific class doesn't have any logic to trigger it.

Scenario 1: Forgotten Invocation (Logic Bug)

This is the most common scenario for beginners. You declared the event so other classes could subscribe to it, but you forgot to actually "push the button."

Example of Error

using System;

public class ProcessRunner
{
// ⛔️ Warning CS0067: The event 'ProcessCompleted' is never used
public event EventHandler ProcessCompleted;

public void Run()
{
Console.WriteLine("Process running...");
// Logic finishes here, but we forgot to tell subscribers!
}
}

Solution: Raise the Event

You need to invoke the event where appropriate, usually checking for null (no subscribers) first.

using System;

public class ProcessRunner
{
public event EventHandler ProcessCompleted;

public void Run()
{
Console.WriteLine("Process running...");

// ✅ Correct: Notify subscribers that the work is done
// The '?.Invoke' pattern is the standard, thread-safe way to raise events.
ProcessCompleted?.Invoke(this, EventArgs.Empty);
}
}

Scenario 2: Unused Interface Events

This scenario is common in patterns like MVVM or when implementing generic interfaces. An interface (like ICommand or INotifyPropertyChanged) might legally require you to define an event, but your specific implementation is static or immutable and never needs to raise it.

Problem

Since the interface forces you to declare the event, but you don't write code to raise it, the compiler generates the warning.

using System;
using System.Windows.Input; // Example using ICommand

public class AlwaysExecutableCommand : ICommand
{
public void Execute(object parameter) { /* Do work */ }
public bool CanExecute(object parameter) => true;

// ⛔️ Warning CS0067: The interface requires this event,
// but since CanExecute is always true, we never raise it.
public event EventHandler CanExecuteChanged;
}

You can define the event's add and remove accessors manually with empty bodies. This tells the compiler: "I am taking manual control of this event, don't generate a backing field for me." Since there is no backing field to be "unused," the warning disappears.

public class AlwaysExecutableCommand : ICommand
{
public void Execute(object parameter) { /* ... */ }
public bool CanExecute(object parameter) => true;

// ✅ Correct: Manually implement accessors to satisfy the interface
// without generating a warning or a backing field.
public event EventHandler CanExecuteChanged
{
add { }
remove { }
}
}

Solution B: Pragma Suppression

If you prefer keeping the code short, you can explicitly tell the compiler to ignore this specific warning for this specific line.

public class AlwaysExecutableCommand : ICommand
{
// ... methods ...

// ✅ Correct: Warning suppressed locally
#pragma warning disable CS0067
public event EventHandler CanExecuteChanged;
#pragma warning restore CS0067
}
note

Assignment Trick: Some developers assign a dummy delegate to avoid the warning: public event EventHandler MyEvent = delegate { };. While this removes the warning and removes the need for null checks, it allocates unnecessary memory for a delegate that is never used. Solution A (Accessors) is generally preferred for interface compliance.

Conclusion

CS0067 is a helpful reminder that an event is currently useless.

  1. Check your logic: Did you forget to type MyEvent?.Invoke()? If so, fix the logic.
  2. Check your interfaces: If you are forced to define an event you don't need, use { add { } remove { } } to implement it cleanly without overhead or warnings.