簡體   English   中英

C#中有什么方法可以用擴展方法覆蓋類方法?

[英]Is there any way in C# to override a class method with an extension method?

有時候我想用擴展方法覆蓋類中的方法。 在C#中有什么方法可以做到這一點?

例如:

public static class StringExtension
{
    public static int GetHashCode(this string inStr)
    {
        return MyHash(inStr);
    }
}

我想要這樣做的一種情況是能夠將字符串的哈希存儲到數據庫中,並且使用該字符串類的哈希的所有類(例如Dictionary等)都使用相同的值。內置的.Net哈希算法不能保證從一個版本的Framework到下一個版本都兼容,我想用自己的版本替換它。

在其他情況下,我也想用擴展方法覆蓋類方法,因此它不僅特定於字符串類或GetHashCode方法。

我知道我可以通過將現有類子類化來做到這一點,但是在很多情況下能夠通過擴展來做到這一點很方便。

沒有; 擴展方法永遠不會比具有適當簽名的實例方法優先,並且永遠不會參與多態性( GetHashCodevirtual方法)。

如果該方法具有不同的簽名,則可以完成-在您的情況下:否。

但是否則,您需要使用繼承來完成您要尋找的事情。

據我所知答案是否定的,因為擴展方法不是實例,對我來說更像是一種智能感知功能,讓您可以使用類的實例來調用靜態方法。 我認為您的問題的解決方案可以是攔截器,該攔截器攔截特定方法(例如GetHashCode())的執行並執行其他操作。要使用此類攔截器(例如Castle Project所提供的),應使用一個實例化所有對象。對象工廠(或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

這使您可以隨意在類方法和擴展方法之間來回跳動,但需要添加重復的“傳遞”方法才能進入所需的“作用域”。 我稱此范圍為缺少更好的詞。 希望有人能讓我知道它的真正含義。

您可能已經猜到我的“傳遞”方法名稱了,我也曾想過將委托傳遞給他們的想法,希望一個或兩個方法可以充當具有相同簽名的多個方法的傳遞。 不幸的是,一旦委托被解壓縮,就不會總是選擇類方法而不是擴展方法,即使從另一個擴展方法內部也是如此。 “范圍”不再重要。 盡管我並沒有非常多地使用Action和Func代表,所以也許更有經驗的人可以弄清楚這一點。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM