Reputation: 4231
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?
Upvotes: 1
Views: 745
Reputation: 20772
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.
Upvotes: 0
Reputation: 10452
GetOutput()
has to be an instance method, and cannot be static if you wish to extend it.
Upvotes: 1
Reputation: 61
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?
Upvotes: 2