<style> .reveal-up, .reveal-left, .reveal-right, .reveal-stagger > * { opacity: 1 !important; transform: none !important; } </style>
  1. Learn
  2. C#
  3. Functional C# and LINQ
All lessons in this course

Lesson 40 of 60 10 minIntermediate

Extension methods

Add your own methods to existing types, even ones you can’t change, and understand how LINQ is built from them.

You can’t edit the string class or a third-party library. But you can extend them: an extension method is a static method that you call as if it were an instance method of the type.

Interactive

Adding methods to string

StringExtensions.cs
public static class StringExtensions{    public static string ToTitleCase(this string s)        => CultureInfo.InvariantCulture.TextInfo.ToTitleCase(s.ToLower());}
You writetext.ToTitleCase()
The compiler turns it intoStringExtensions.ToTitleCase(text)
Result"Steel Beam Schedule For Level Two"

The this before the first parameter is what makes it an extension method. string itself is unchanged; you just get nicer syntax and IntelliSense shows the method on every string.

Writing one

Extensions.cs
public static class DoubleExtensions          // 1. a static class{    // 2. a static method  3. 'this' before the first parameter    public static double MmToM(this double mm) => mm / 1000.0;     public static bool IsBetween(this double value, double min, double max)        => value >= min && value <= max;} double depth = 300;Console.WriteLine(depth.MmToM());              // reads naturallyConsole.WriteLine(4.5.IsBetween(3, 6));
Output
0.3
True
  • The class must be static and not nested; the method must be static.
  • The first parameter, marked this, is the object the method is “called on”.
  • The namespace containing the class must be imported with using to see the methods.
  • Extension methods can only use the type’s public members: they don’t break encapsulation.

Extending interfaces

IEnumerableExt.cs
public static class MemberExtensions{    public static double TotalWeight(this IEnumerable<Beam> beams)    {        double sum = 0;        foreach (var b in beams) sum += b.Kg;        return sum;    }} List<Beam> level1 = LoadLevel(1);Beam[] picked = GetSelection();Console.WriteLine(level1.TotalWeight());    // works on a List…Console.WriteLine(picked.TotalWeight());    // …and an array: both are IEnumerable<Beam>

This is exactly how LINQ works: Where, Select, OrderBy and friends are extension methods on IEnumerable<T> in the System.Linq namespace. That is why every collection gets them for free.

Rules of thumb

  • If a type has an instance method with the same signature, the instance method wins.
  • Use extensions for small, general helpers. Don’t hide important business logic in them.
  • Group them in classes named after what they extend: StringExtensions, GeometryExtensions.
Quick check

What makes a static method an extension method?

Quick check

text.WordCount() is compiled as…

Practice

Write an extension method string Repeat(this string s, int times) and bool IsPalindrome(this string s) (ignore case). Test with "ab".Repeat(3) and "Level".IsPalindrome().

Show the solution
Solution.cs
public static class StringExtensions{    public static string Repeat(this string s, int times)        => string.Concat(Enumerable.Repeat(s, times));     public static bool IsPalindrome(this string s)    {        string lower = s.ToLowerInvariant();        for (int i = 0, j = lower.Length - 1; i < j; i++, j--)            if (lower[i] != lower[j]) return false;        return true;    }} Console.WriteLine("ab".Repeat(3));Console.WriteLine("Level".IsPalindrome());
Output
ababab
True

Remember

  • Extension methods are static methods called like instance methods.
  • Declare them in a static class with this on the first parameter.
  • Extending an interface gives the method to every type that implements it.
  • LINQ is a set of extension methods on IEnumerable<T>.
0 of 60 lessons completed