I found a class that relies on a method that is defined in an extension of it. Is this a pattern?

I found a class that looks something like:

using System;
// no using statement that brings either IMyClass or
// MyClassExtensions into scope

namespace Org.Foo {

    class MyClass {

    public void QuizzicalMethod(IMyClass thingy,
                                string stringToPass) {
        thingy.ExtensionMethod(StringToPass);
    }
}

There is an IMyClass interface definition in IMyClass.cs in the codebase (in the same namespace and directory), but it contains no definition for QuizzicalMethod. Instead, MyClassExtensions.cs has:

using System;
namespace Org.Foo {
    public static class MyClassExtensions {
        public static void ExtensionMethod (this IMyClass self,
                                            string stringToPass) {
            // Do some stuff
        }
    }
}

Thus, MyClassExtensions is clearly out of scope when MyClass is defined, and thus when QuizzicalMethod--which uses IMyClassExtensions.ExtensionMethod--is defined. It seems to me like both the parameter list of the QuizzicalMethod definition and its call of thingy.ExtensionMethod ought to break. (Makes me wonder if there's a code coverage issue in the tests.) This leads to some questions:

  • How does this compile without an error?
  • Why would a class author even want to bring QuizzicalMethod out of the class definition and put it into an extension?
  • Does this fit an existing named pattern?
  • Is there some kind of scoping exception or late-binding going on? If so, how does it not break everything else in C#?

Thanks in advance!

EDIT: Fixed some typos.

Jon Skeet
people
quotationmark

Thus, MyClassExtensions is clearly out of scope when MyClass is defined

Nope, both MyClassExtensions and MyClass are declared in the same namespace. You don't need a using directive to invoke an extension method in the same namespace or an enclosing namespace.

You haven't explained where IMyClass is declared, so I can't comment on that.

From section 7.6.5.2 of the C# 5 specification (talking about finding a class C containing an extension method):

The search for C proceeds as follows:

  • Starting with the closest enclosing namespace declaration, continuing with each enclosing namespace declaration, and ending with the containing compilation unit, successive attempts are made to find a candidate set of extension methods:
  • If the given namespace or compilation unit directly contains non-generic type declarations Ci with eligible extension methods Mj, then the set of those extension methods is the candidate set.
  • If namespaces imported by using namespace directives in the given namespace or compilation unit directly contain non-generic type declarations Ci with eligible extension methods Mj, then the set of those extension methods is the candidate set.

Basically, this is just an extension method. Without knowing more of the real context, we can't comment on why this is an extension method rather than a method on IMyClass.

people

See more on this question at Stackoverflow