Empty Function Body
ID |
csharp.empty_function_body |
Severity |
info |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
CSharp |
Tags |
dead-code, reliability |
Description
Reports a method whose body is an empty { } block (or a block containing only
comments). An empty method silently does nothing while looking like a real
implementation; callers cannot tell that the operation was a no-op.
Several shapes where the empty body is required, not accidental, are exempt:
override methods and virtual Template-Method hooks (the member cannot be
omitted, or exists precisely so a derived class can override it selectively),
a same-file interface implementation, a Dispose()/DisposeAsync() on a class
that already implements IDisposable/IAsyncDisposable, and Razor Pages
convention handlers (OnGet on a PageModel, required for routing). Units
carrying a generated-code marker (// <auto-generated> header, the legacy
Visual Studio designer header, or [GeneratedCode]) are skipped entirely.
Rationale
A method with an empty body is almost always a sign of an incomplete change: a
stub left after a refactoring, a callback that was never wired up, or a method
that should have been deleted. Comments do not count as statements — a body
that contains only // TODO is still empty and still misleading.
abstract, partial and extern methods are excluded because the language
either forbids a body or expects the implementation to be supplied elsewhere.
public class Service
{
public void Start() // OK — body has statements
{
Initialize();
}
public void Stop() // FLAW — body is empty
{
}
public void Reset()
{ // FLAW — only a comment, not a statement
// TODO: implement
}
public abstract void Tick(); // OK — abstract method has no body
protected virtual void Configure() { } // OK — virtual Template-Method hook
}
public interface IWorker { void Run(); }
public class NoOpWorker : IWorker
{
public void Run() { } // OK — same-file interface implementation
}
Remediation
Decide whether the method should do something, be removed, or be declared
abstract to make the "no default behavior" explicit. If a deliberate no-op
is required — a virtual hook with nothing to do by default, an interface
member that has to exist, a Null Object Dispose() — leaving the body empty
is the correct implementation and the rule already recognizes it; document the
intent with a comment only if the reason is not obvious from the shape alone.