Extension methods: custom types, value types and using

1 min read
On trails:CSCOREstep 9/11

An extension method can extend any type, including your own (see extension methodsExtension methodsAdd methods to a type you can't change, without touching its source or subclassing it.Opens in a new tab).

Types and interfaces

Extending an interface is more powerful than extending a class: every implementing type gets the method.

C#
static class EnumerableExtensions{    public static bool IsEmpty<T>(this IEnumerable<T> source) => !source.Any();} List<int> list = new List<int>();Console.WriteLine(list.IsEmpty()); // true: works on any IEnumerable<T>

The compiler rewrites email.IsValidEmail() into the static call StringExtensions.IsValidEmail(email).

Value types

A struct is copied when passed, so an extension method changes only its copy. this ref Point (C# 7.2) changes the original. A reference type needs no ref (see value types and reference typesValue types and reference typesA value type variable holds the value. A reference type variable holds a reference to an object.Opens in a new tab).

C#
struct Point{    public int X, Y;} static class PointExtensions{    // Looks like it modifies the struct, but it only changes a copy    public static void MoveWrong(this Point p) => p.X += 10;     public static void MoveRight(this ref Point p) => p.X += 10; // C# 7.2+} // Point pt = new Point { X = 1, Y = 2 };// pt.MoveWrong();// Console.WriteLine(pt.X); // still 1// pt.MoveRight();// Console.WriteLine(pt.X); // 11

Namespaces

An extension method is visible only where its namespace is imported, which keeps unrelated extensions from crowding every type. LINQ needs using System.Linq; for this reason. Extension methods cannot reach private members.

C#
namespace MyUtils{    public static class StringExtensions    {        public static bool IsValidEmail(this string s) => s.Contains("@");    }} // In another file:using MyUtils; // now the compiler can see the extension method string email = "test@test.com";email.IsValidEmail(); // works, and shows up in autocomplete