【问题标题】:Implement IEnumerable<SomeClass> extension method in SomeClass在 SomeClass 中实现 IEnumerable<SomeClass> 扩展方法
【发布时间】:2013-06-09 13:57:49
【问题描述】:

我有这样的课:

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

这个类不是静态的,但我想让GetOutput 成为IEnumerable&lt;SomeClass&gt; 的扩展方法。因此,我创建了一个新的静态类:

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

有没有更优雅的方法来做到这一点?为什么不允许我们将SomeClass.GetOutput 设为扩展方法?

【问题讨论】:

  • 因为那将是一个实例方法。
  • 他们本可以实现这一点,但他们决定不这样做。请参阅此处了解先前的讨论:stackoverflow.com/questions/2731695/… 和此处:stackoverflow.com/questions/7405751/…
  • @newStackExchangeInstance 他仍在扩展接口IEnumerable&lt;SomeClass&gt;。您不能为接口内的实例方法提供在该接口内编写的实现。此外,IEnumerable&lt;&gt; 是在 BCL 中定义的,因此我们无法为其配备更多的实例方法。只有扩展方法。

标签: c# extension-methods


【解决方案1】:

不幸的是,没有更优雅的方法可以做到这一点。

这里已经回答了为什么不允许他们:Why are extension methods only allowed in non-nested, non-generic static class?

【讨论】:

    【解决方案2】:

    GetOutput() 必须是一个实例方法,如果你想扩展它不能是静态的。

    【讨论】:

    • -1:只能用静态类来完成。在这种情况下,this 并不表示声明类型的实例,而是告诉编译器该方法可以用作扩展。
    • @csharpler 包含扩展的类必须是静态的,但您要扩展的类不能。
    • 他问的不是这个。
    【解决方案3】:

    为什么不允许我们将 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;
        }
    }
    

    GetOutputExtensionAspectAttribute 标记,它派生自 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 中定义扩展方法,特别是因为它可以在与 SomeClass. 相同的命名空间甚至相同的 .cs 文件中完成

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-01
      • 2018-12-13
      • 2020-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多