在C#中有没有办法用扩展方法重写类方法?

在C#中有没有办法用扩展方法重写类方法?,c#,extension-methods,overriding,C#,Extension Methods,Overriding,在某些情况下,我希望用扩展方法重写类中的方法。有没有办法在C#中做到这一点 例如: public static class StringExtension { public static int GetHashCode(this string inStr) { return MyHash(inStr); } } 我希望这样做的一种情况是,能够将字符串的哈希存储到数据库中,并让所有使用字符串类哈希的类(即字典等)使用相同的值,因为内置的.Net哈希算法不能

在某些情况下,我希望用扩展方法重写类中的方法。有没有办法在C#中做到这一点

例如:

public static class StringExtension
{
    public static int GetHashCode(this string inStr)
    {
        return MyHash(inStr);
    }
}
我希望这样做的一种情况是,能够将字符串的哈希存储到数据库中,并让所有使用字符串类哈希的类(即字典等)使用相同的值,因为内置的.Net哈希算法不能保证从一个版本的框架兼容到下一个版本,我想用我自己的来代替它

我还遇到过另一种情况,我想用扩展方法重写一个类方法,这样它就不仅仅局限于string类或GetHashCode方法


我知道我可以通过现有类的子类化来实现这一点,但在很多情况下,通过扩展来实现这一点会很方便;扩展方法从不优先于具有适当签名的实例方法,也从不参与多态性(
GetHashCode
是一种
virtual
方法)。

如果该方法具有不同的签名,那么就可以这样做——因此在您的情况下:否


但除此之外,您需要使用继承来完成所需的任务。

据我所知,答案是否定的,因为扩展方法不是实例。对我来说,它更像是一种智能感知工具,允许您使用类的实例调用静态方法。
我认为您的问题的解决方案可以是拦截特定方法(例如GetHashCode())的执行并执行其他操作的拦截器。要使用这样的拦截器(如Castle项目提供的拦截器),所有对象都应该使用对象工厂(或Castle中的IoC容器)实例化因此,可以通过运行时生成的动态代理拦截这些接口。(Caslte还允许拦截类的虚拟成员)

我找到了一种方法,可以使用与类方法相同的签名来调用扩展方法,但是它看起来不是很优雅。在使用扩展方法时,我注意到一些未记录的行为。示例代码:

public static class TestableExtensions
{
    public static string GetDesc(this ITestable ele)
    {
        return "Extension GetDesc";
    }

    public static void ValDesc(this ITestable ele, string choice)
    {
        if (choice == "ext def")
        {
            Console.WriteLine($"Base.Ext.Ext.GetDesc: {ele.GetDesc()}");
        }
        else if (choice == "ext base" && ele is BaseTest b)
        {
            Console.WriteLine($"Base.Ext.Base.GetDesc: {b.BaseFunc()}");
        }
    }

    public static string ExtFunc(this ITestable ele)
    {
        return ele.GetDesc();
    }

    public static void ExtAction(this ITestable ele, string choice)
    {
        ele.ValDesc(choice);
    }
}

public interface ITestable
{

}

public class BaseTest : ITestable
{
    public string GetDesc()
    {
        return "Base GetDesc";
    }

    public void ValDesc(string choice)
    {
        if (choice == "")
        {
            Console.WriteLine($"Base.GetDesc: {GetDesc()}");
        }
        else if (choice == "ext")
        {
            Console.WriteLine($"Base.Ext.GetDesc: {this.ExtFunc()}");
        }
        else
        {
            this.ExtAction(choice);
        }
    }

    public string BaseFunc()
    {
        return GetDesc();
    }
}
我注意到,如果我从扩展方法内部调用第二个方法,它将调用与签名匹配的扩展方法,即使有一个类方法也与签名匹配。例如,在上面的代码中,当我调用ExtFunc()时,它反过来调用ele.GetDesc(),我得到的是返回字符串“Extension GetDesc”,而不是我们所期望的字符串“Base GetDesc”

测试代码:

var bt = new BaseTest();
bt.ValDesc("");
//Output is Base.GetDesc: Base GetDesc
bt.ValDesc("ext");
//Output is Base.Ext.GetDesc: Extension GetDesc
bt.ValDesc("ext def");
//Output is Base.Ext.Ext.GetDesc: Extension GetDesc
bt.ValDesc("ext base");
//Output is Base.Ext.Base.GetDesc: Base GetDesc
这允许您随意在类方法和扩展方法之间来回跳转,但需要添加重复的“传递”方法以进入所需的“范围”。我在这里称之为范围,因为没有更好的词。希望有人能让我知道它到底叫什么


您可能已经从我的“pass-through”方法名称中猜到了,我还玩弄了将委托传递给它们的想法,希望一个或两个方法可以充当具有相同签名的多个方法的pass-through。不幸的是,事实并非如此,因为一旦解包委托,它总是选择类方法而不是扩展方法,即使是从另一个扩展方法内部。“范围”不再重要。我没有太多地使用Action和Func委托,因此可能有更有经验的人可以理解这一部分。

既然字典是内存中的数据结构,那么哈希算法是否会从一个版本的框架更改到下一个版本又有什么区别呢?如果框架版本发生更改,那么显然应用程序已重新启动,字典已重新构建。“…从不参与多态性(GetHashCode是一个虚拟方法)”您能否以另一种方式解释为什么扩展方法由于是虚拟的而从不参与多态性?我很难理解这两种说法之间的联系。@Alex提到虚拟,我只是想澄清多态性的含义。实际上,在GetHashCode的所有使用中,具体类型都是未知的,因此多态性在起作用。因此,即使扩展方法在常规编译器中具有优先权,它们也不会有帮助。OP真正想要的是猴子修补术。c#和.net不方便使用的方法。令人遗憾的是,在c#中有太多误导性的无意义方法,例如数组中的
.ToString()
。这绝对是一个必需的功能。那你为什么不得到一个编译器错误呢?例如,我打字<代码>命名空间系统{public static class{public static string ToLower(此字符串s){return s.ToUpper()+“我是恶意的”}}}}@LowLevel为什么要这样做?