An extension method adds a method to an existing type without modifying it, inheriting from it or wrapping it. You write an ordinary static method, mark its first parameter with this, and callers use it with dot syntax as if the type had always had it:
Output:
Extension methods let yo...
12
short
Extension...
title.Truncate(24) is compiled to exactly StringExtensions.Truncate(title, 24). The dot syntax is only a convenience: the method is still static, still lives in StringExtensions, and can only use the public members of string.
The Rules for Declaring One
- The method must be
staticand live in a class that isstatic, non-generic and not nested inside another class. A non-static or generic class gives CS1106,Extension method must be defined in a non-generic static class; a nested one gives CS1109,Extension methods must be defined in a top level static class. thisgoes on the first parameter only, and that parameter's type is the type being extended. Further parameters are normal.- The method may itself be generic (
this IEnumerable<T> source), even though the class may not. - It sees only what any outside code sees: public (and, within the same assembly, internal) members. Private fields stay private.
The convention is to name the class after what it extends (StringExtensions, EnumerableExtensions) and to group them in a namespace such as MyApp.Extensions.
Extending Interfaces and IEnumerable<T>
Extending an interface adds the method to every type that implements it. Extending IEnumerable<T> therefore gives the method to arrays, lists, sets, dictionaries' key collections and LINQ query results at once:
Output:
9.5
50
65
f0 f3 f6
EveryNth is generic: T is inferred from the receiver, so it works for strings here and for any other element type. Because it uses yield return, it is lazy like the built-in LINQ operators and can be chained with them.
LINQ Is Built on Extension Methods
Where, Select, OrderBy, Sum, First and the rest of LINQ are extension methods on IEnumerable<T>, defined in the static class System.Linq.Enumerable. That is why using System.Linq; has to be at the top of a file before list.Where(...) compiles, and why LINQ works on every collection type without any of them implementing a Where method:
Output:
72, 88, 95
72, 88, 95
The two lines are the same code. The extension syntax turns nested calls that read inside-out into a chain that reads in the order the steps happen, which is the main reason extension methods exist: they were added in C# 3 together with LINQ. The LINQ page covers the operators.
The Namespace Must Be Imported
An extension method is only in scope when the namespace of its static class is imported with using. Without it, the call fails as if the method did not exist:
error CS1061: 'string' does not contain a definition for 'Truncate' and no accessible extension method 'Truncate' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)
Add the using for the extensions' namespace (or, from C# 10, a global using once for the project):
Output:
EUR 49.90
The flip side is useful: an extension method you do not want everywhere can live in a namespace that only some files import.
Instance Methods Win
When a type already has an applicable instance method, the compiler uses it and never considers the extension. An extension with the same signature is dead code at every call site that uses dot syntax:
Output:
Invoice (instance method): 120
Invoice (extension): 120 USD
extension: only reachable as a static call
The one-argument extension lost to the instance method; the two-argument one was used because no instance method takes a string. This also means a library update that adds an instance method with your extension's name silently switches your calls over to the library's version. Choose extension names that are unlikely to collide.
Calling on null
Since the call is really a static call, a null receiver does not throw at the call site. The method receives null as its first argument and decides what that means:
Output:
True
AL
ArgumentNullException: fullName
missing.IsBlank() returning true is convenient, but it can surprise readers who expect a member call on null to throw. Accept null only in methods whose name makes it obvious (IsBlank, OrEmpty); elsewhere, throw ArgumentNullException like LINQ does.
Extending Enums
Enums cannot have methods of their own, which makes them a natural target:
enum OrderStatus { Pending, Paid, Shipped, Delivered, Cancelled }
static class OrderStatusExtensions
{
public static bool IsFinal(this OrderStatus s) =>
s == OrderStatus.Delivered || s == OrderStatus.Cancelled;
}
// usage: if (order.Status.IsFinal()) { ... }
Extension Members in C# 14
Until C# 14, only methods could be extensions. C# 14 added extension blocks, which group members for one receiver and allow extension properties and static members too:
// C# 14 and later
public static class StringExtensions
{
extension(string s)
{
public bool IsBlank => string.IsNullOrWhiteSpace(s); // extension property
public string Truncate(int max) => s.Length <= max ? s : s[..max] + "...";
}
}
Classic this-parameter extension methods remain valid and are what almost all existing code and libraries use.
When to Write One
Extension methods fit when you do not own the type (string, DateTime, framework interfaces), when you want the same helper on every implementation of an interface, or when a chain reads better than nested calls. When you own the class, add a real instance method instead: it can use private state and shows up where readers look for it. And avoid extending object, which puts your method in the completion list of every value in the program.
Frequently Asked Questions
What is an extension method in C#?
A static method that can be called as if it were an instance method of another type. You write it in a static class and put this before its first parameter: public static bool IsBlank(this string s) => string.IsNullOrWhiteSpace(s);. Then name.IsBlank() works on any string, without changing or inheriting from string.
Why is my extension method not found?
Extension methods are only visible when their namespace is imported. If the static class is in MyApp.Extensions, add using MyApp.Extensions; to the file that calls it; otherwise the compiler reports CS1061, saying the type contains no definition and no accessible extension method of that name. Also check that the class is static, non-generic and not nested.
Can an extension method override an instance method?
No. The compiler looks for an applicable instance method first and only considers extension methods when none exists. An extension with the same name and parameters as an instance method is silently ignored at every call site that uses instance syntax.
Can you call an extension method on null in C#?
Yes. The call compiles to a static method call with null as the first argument, so no NullReferenceException is thrown at the call itself. The method decides what to do: treat null as a valid input (like an IsNullOrEmpty-style helper) or throw ArgumentNullException, as LINQ's methods do.
Are there extension properties in C#?
Not before C# 14. Until then, only methods can be extensions, so a would-be property is written as a method (GetFullName()). C# 14 added extension blocks, which can declare extension properties and static members as well as methods.