1

I have a class like this:

public class SomeClass
{
    public static IEnumerable<SomeClass> GetOutput(IEnumerable<SomeClass> items)
    {
        //Do stuff
    }
}

This class is not static, but I want to make GetOutput an extension method for IEnumerable<SomeClass>. As such, I create a new static class:

public static class SomeClassExtensionMethods
{
    public static IEnumerable<SomeClass> GetOutput(this IEnumerable<SomeClass> items)
    {
        return SomeClass.GetOutput(items);
    }
}

Is there any more elegant way to do this? Why aren't we allowed to make SomeClass.GetOutput an extension method?

Andrew Sun
  • 4,101
  • 6
  • 36
  • 53
  • Because that would be an instance method. – It'sNotALie. Jun 09 '13 at 13:58
  • 2
    They could have implemented that, but they decided not to. See here for a previous discussion: http://stackoverflow.com/questions/2731695/extension-method-requires-class-to-be-static and here: http://stackoverflow.com/questions/7405751/why-cant-static-method-in-non-static-class-be-an-extension-method – Matthew Watson Jun 09 '13 at 14:10
  • 3
    @newStackExchangeInstance He's still extending **an interface**, `IEnumerable`. You can't give an instance method inside an interface an implementation written inside that interface. Besides, `IEnumerable<>` is defined in the BCL, so we cannot equip it with more instance methods. Only extension methods. – Jeppe Stig Nielsen Jun 09 '13 at 14:27

3 Answers3

2

There is no more elegant way to do this unfortunately.

Why they aren't allowed was already answered here: Why are extension methods only allowed in non-nested, non-generic static class?

Community
  • 1
  • 1
Mike D
  • 61
  • 2
1

GetOutput() has to be an instance method, and cannot be static if you wish to extend it.

Tom Studee
  • 10,316
  • 4
  • 38
  • 42
  • -1: It can only be done with a static class. In this case, `this` doesn't mean an instance of the declaring type, but tells the compiler that this method may be used as an extension. – pascalhein Jun 09 '13 at 14:15
  • @csharpler The class containing the extensions has to be static, but the class you are extending cannot be. – Tom Studee Jun 09 '13 at 14:32
  • 1
    this is not what he asked about. – pascalhein Jun 09 '13 at 14:33
0

Why aren't we allowed to make SomeClass.GetOutput an extension method?

You can but not with the standard C# tools.

To the C# compiler, an extension method for a type is a static method that takes an instance of that type as its first parameter and is marked with System.Runtime.CompilerServices.ExtensionAttribute.

When defining an extension method in C#, the C# compiler won't allow the application of that attribute at all, suggesting that you use the this syntax, which does have the cited requirements. So, you could define the SomeClass in some other language or use a tool that adds the attribute after the C# compiler is done.

PostSharp (non-free edition) can do that. Just mark GetOutput with a different attribute and write code to replace it with System.Runtime.CompilerServices.ExtensionAttribute.

public class SomeClass
{
    [ExtensionAspect]
    public static IEnumerable<SomeClass> GetOutput(IEnumerable<SomeClass> items)
    {
        return items;
    }
}

GetOutput is marked with ExtensionAspectAttribute, which is derived from a PostSharp aspect. Post-processing during the build runs the ProvideAspect method, which adds the desired attribute.

[AttributeUsage(AttributeTargets.Method)]
public class ExtensionAspectAttribute : MethodLevelAspect, IAspectProvider
{
    public IEnumerable<AspectInstance> ProvideAspects(object targetElement)
    {
        var constructorInfo = typeof (System.Runtime.CompilerServices.ExtensionAttribute).GetConstructor(Type.EmptyTypes);
        var objectConstruction = new ObjectConstruction(constructorInfo);
        var aspectInstance = new CustomAttributeIntroductionAspect(objectConstruction);
        yield return new AspectInstance(targetElement, aspectInstance);

    }
}

So, in another project that references the binary assembly for SomeClass, this works:

var items = new [] { new SomeClass() };
var results = items.GetOutput();

That satisfies the C# compiler, however Intellisense doesn't see it as an extension method and ReSharper colors it as an error.


Of course, this is an academic exercise because there is little reason to not define the extension method in SomeClassExtensionMethods especially since it can be done in the same namespace and even the same .cs file as SomeClass.

Tom Blodget
  • 20,260
  • 3
  • 39
  • 72