我有一个这样的课程:
public class SomeClass
{
public static IEnumerable<SomeClass> GetOutput(IEnumerable<SomeClass> items)
{
//Do stuff
}
}
此类不是静态的,但我希望GetOutput
为IEnumerable<SomeClass>
的扩展方法。因此,我创建了一个新的静态类:
public static class SomeClassExtensionMethods
{
public static IEnumerable<SomeClass> GetOutput(this IEnumerable<SomeClass> items)
{
return SomeClass.GetOutput(items);
}
}
还有更优雅的方法吗?为什么我们不允许SomeClass.GetOutput
作为扩展方法?
答案 0 :(得分:2)
不幸的是,没有更优雅的方法可以做到这一点。
为什么他们不被允许已经在这里回答:Why are extension methods only allowed in non-nested, non-generic static class?
答案 1 :(得分:1)
GetOutput()
必须是实例方法,如果您希望扩展它,则不能是静态的。
答案 2 :(得分:0)
为什么我们不允许SomeClass.GetOutput成为扩展方法?
您可以,但不能使用标准C#工具。
对于C#编译器,类型的扩展方法是一种静态方法,它将该类型的实例作为其第一个参数并标记为System.Runtime.CompilerServices.ExtensionAttribute.
在C#中定义扩展方法时,C#编译器根本不允许应用该属性,这表明您使用的this
语法具有引用的要求。因此,您可以在某种其他语言中定义SomeClass
,或使用在C#编译器完成后添加属性的工具。
PostSharp(非免费版)可以做到这一点。只需使用其他属性标记GetOutput
,然后编写代码以将其替换为System.Runtime.CompilerServices.ExtensionAttribute.
public class SomeClass
{
[ExtensionAspect]
public static IEnumerable<SomeClass> GetOutput(IEnumerable<SomeClass> items)
{
return items;
}
}
GetOutput
标有ExtensionAspectAttribute
,来自PostSharp方面。构建期间的后处理运行ProvideAspect
方法,该方法添加了所需的属性。
[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);
}
}
因此,在引用SomeClass的二进制程序集的另一个项目中,这可以工作:
var items = new [] { new SomeClass() };
var results = items.GetOutput();
满足C#编译器,但Intellisense不会将其视为扩展方法,而ReSharper将其视为错误。
当然,这是一个学术练习,因为没有理由不在SomeClassExtensionMethods
中定义扩展方法,特别是因为它可以在同一名称空间中完成,甚至可以在{{1}相同的.cs文件中完成}