简体   繁体   English

是否可以为抽象类编写扩展方法

[英]Is it possible to write a extension method for an abstract class

Why I'm unable to extend an abstract class. 为什么我无法扩展抽象类。 Is there any work around to achieve this? 有没有解决这个问题的工作?

In silverlight, Enum.GetNames is missing. 在Silverlight中,Enum.GetNames不见了。 So, I would like to extend it and have it in my utility assembly. 所以,我想扩展它,并在我的实用程序集中。 By then, got into this. 到那时,进入了这个。

The problem here is not that you can't add an extension method to an abstract class (you can - you can add an extension method to any type) - it's that you can't add a static method to a type with extension methods. 这里的问题不在于您不能将扩展方法添加到抽象类(您可以 - 您可以向任何类型添加扩展方法) - 这是您不能将静态方法添加到具有扩展方法的类型。

Extension methods are static methods that present themselves in C# as instance methods. 扩展方法是静态方法,它们将自己作为实例方法呈现在C#中。 But they're still static. 但他们仍然是静止的。 Adding a static method to a type requires the ability to redefine the type, which you can only do if you have the source code :) 向类型添加静态方法需要能够重新定义类型,只有拥有源代码才能执行此操作:)

Best bet, if you want this method, is to write your own static and see if you can perhaps rip the code out of reflector. 如果你想要这个方法,最好的办法是编写自己的静态函数,看看你是否可以将代码从反射器中删除。

However, it's entirely possible that it's not there because it's physically not supported in Silverlight (I don't know - I haven't investigate) 但是,它完全有可能不存在,因为它在Silverlight中实际上不受支持(我不知道 - 我没有调查)

EDIT 编辑

Following on from your comment - and I hope that I've understood you here - I think what you want to be able to do is something like this (targetting object to prove the point): 继续你的评论 - 我希望我在这里了解你 - 我认为你想要做的就是这样(目标object来证明这一点):

public static class ExtraObjectStatics
{
  public static void NewStaticMethod()
  {

  }
}

public class Test
{
  public void foo()
  {
    //You can't do this - the static method doesn't reside in the type 'object'
    object.NewStaticMethod();
    //You can, of course, do this
    ExtraObjectStatics.NewStaticMethod();
  }
}

If you think about it - of course you can't inject new static methods into an existing type because, like I said in paragraph two, you have to be able to recompile the underlying type; 如果你考虑一下 - 当然你不能将新的静态方法注入到现有类型中,因为就像我在第二段中所说的那样,你必须能够重新编译底层类型; and there simply is no way around that. 而且根本没有办法解决这个问题。

What you can do is (and I don't actually recommend this - but it's an option) create yourself a new type called Enum and place it inside a new namespace: 你可以做的是(我实际上并不推荐这个 - 但它是一个选项)创建一个名为Enum的新类型并将其放在一个新的命名空间中:

namespace MySystem
{
  public class Enum
  {
    public static string[] GetNames()
    {
      //don't actually know how you're going to implement it :)
    }
  }
}

And now - when you want to use it, what you can't do is this: 现在 - 当你想要使用它时,你不能做的是:

using System;
using MySystem;

namespace MyCode
{
  public class TestClass
  {
    public static void Test()
    {
      Enum.GetNames(); //error: ambiguous between System and MySystem
    }
  }
}

Because the using in the outermost scope to both 'System' and 'MySystem' will cause the compiler not to be able to resolve the correct Enum type. 因为在最外层范围内使用'System'和'MySystem'将导致编译器无法解析正确的Enum类型。

What you can do, however, is this: 但是,你可以做的是:

using System;

namespace MyCode
{
  using MySystem; //move using to inside the namespace
  public class TestClass
  {
    public static void Test()
    {
      //will now work, and will target the 'MySystem.Enum.GetNames()'
      //method.
      Enum.GetNames();
    }
  }
}

Now, code within that namespace (within that file only ) will always resolve Enum to the one in your namespace because that's the nearest using directive in terms of scope. 现在,该命名空间内的代码( 在该文件中)将始终将Enum解析为命名空间中的代码,因为就范围而言,这是最近的using指令。

So, you can think of this as overriding the whole Enum type for the benefit of a given namespace that includes a using MySystem; 因此,您可以将此视为覆盖整个Enum类型,以获得包含using MySystem;的给定命名空间的using MySystem; in it. 在里面。

But, it does exactly that - it replaces the existing System.Enum with MySystem.Enum - meaning that you lose all the members of the System.Enum type. 但是,确实如此 - 它将现有的System.Enum 替换MySystem.Enum - 这意味着您将丢失System.Enum类型的所有成员。

You could get around this by writing wrapper methods in your Enum type around the System.Enum versions - making sure that you fully-qualify the type as System.Enum . 您可以通过在System.Enum版本的Enum类型中编写包装器方法来解决这个问题 - 确保您将类型完全限定为System.Enum

Having looked at the implementation of the GetNames method in Reflector - it relies on internal data that I don't think you're going to be able to build... but I would be very interested to hear if you are actually able to reproduce the method in Silverlight. 看过Reflector中的GetNames方法的实现 - 它依赖于我认为你无法构建的内部数据......但是我很想知道你是否真的能够重现Silverlight中的方法。

public abstract class Foo
{
  public abstract void Bar();
}

public static class FooExtensions
{
  // most useless extension method evar
  public static void CallBar(this Foo me)
  {
    me.Bar();
  }
}

Sure, no problem. 好没问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM