Limiting C# extension methods visibility with namespaces

Posted: (EET/GMT+2)

 

Extension methods are a useful feature in C#, and I find myself using them often. Most often, the extensions I write are global to the application, i.e. they can be used everywhere within the application code.

However, sometimes you might wish to limit the scope of extension methods, say, to a certain class. You might wish to do this to improve code readability, limit the number of files in your project, etc.

Now, if you only wanted a single class to have access to a certain extension method (or a set of methods), the first idea might be to write a nested class (class inside a class) to contain the extension. For instance, you might be tempted to write code similar to the following (taken from a WinForms application):

public partial class Form1 : Form
{
  // nested extension class
  internal static class Form1Extensions
  {
    internal static void ShowIt(this string input)
    {
      MessageBox.Show(input);
    }
  }

  public Form1()
  {
    InitializeComponent();
  }

  private void button1_Click(object sender, EventArgs e)
  {
    string message = "Hello World!";
    message.ShowIt();
  }
}

The result of this experiment would be a failure, as it turns out that extension methods have certain limitations, one of them being that you cannot declare an extension method in a nested class.

Still, if you would try to compile the above code, you would get a compiler error with the message "Extension method must be defined in a top level static class; Form1Extensions is a nested class." And if you would look at the C# Language Specification 4.0 section 10.6.9 on page 333, you would hear the same thing: "Extension methods can only be declared in non-generic, non-nested static classes."

Of course, the easy solution would to move the extension class out from inside the Form1 class (but in the same source), but that would give the extension a global reach, something we wanted to avoid.

How would you work around the limitation? One way to do it is this: add your extension class to a new namespace that is nested from your normal application namespace.

In more detail: In C#, a single source file can not only contain the definition of multiple classes, but also multiple namespaces. Create a new namespace in the .cs source code file, and give it some unique name, for instance based on the class name to which you want to limit the extension method. Then, use the "using" statement to refer to the newly added namespace.

Here's a complete example, notice the comments with three stars in them.

using System;
...
// *** reference to the new namespace with the extension method(s)
using WindowsFormsApplication2.Form1Extensions;

// ** regular definition of the class within the app's namespace
namespace WindowsFormsApplication2
{
  public partial class Form1 : Form
  {
    public Form1()
    {
      InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
      string message = "Hello World!";
      message.ShowIt(); // *** extension method
    }
  }
}

// *** the new "private" nsmaespace
namespace WindowsFormsApplication2.Form1Extensions
{
  internal static class Form1Extensions
  {
    internal static void ShowIt(this string input)
    {
      MessageBox.Show(input);
    }
  }
}

Happy hacking!