Znalazłem sposób na wywołanie metody rozszerzającej z taką samą sygnaturą jak metoda klasowa, jednak nie wydaje się ona zbyt elegancka. Podczas zabawy z metodami rozszerzającymi zauważyłem nieudokumentowane zachowanie. Przykładowy kod:
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();
}
}
Zauważyłem, że gdybym wywołał drugą metodę z wnętrza metody rozszerzającej, wywołałaby metodę rozszerzenia, która pasowała do podpisu, nawet jeśli istniałaby metoda klasy, która również pasuje do podpisu. Na przykład w powyższym kodzie, kiedy wywołuję ExtFunc (), który z kolei wywołuje ele.GetDesc (), otrzymuję zwrotny ciąg znaków „Extension GetDesc” zamiast ciągu „Base GetDesc”, którego byśmy się spodziewali.
Testowanie kodu:
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
Pozwala to na dowolne przechodzenie między metodami klas i metodami rozszerzającymi, ale wymaga dodania zduplikowanych metod „przekazujących”, aby uzyskać pożądany „zakres”. Nazywam to zakresem z braku lepszego słowa. Mam nadzieję, że ktoś może mi powiedzieć, jak to się właściwie nazywa.
Mogłeś odgadnąć na podstawie moich nazw metod „tranzytowych”, którymi również bawiłem się pomysłem przekazywania im delegatów w nadziei, że jedna lub dwie metody mogą działać jako przejście dla wielu metod z tym samym podpisem. Niestety nie miało to być tak, że po rozpakowaniu delegata zawsze wybierał metodę klasy zamiast metody rozszerzającej, nawet z wnętrza innej metody rozszerzającej. „Zakres” nie miał już znaczenia. Nie korzystałem zbytnio z delegatów Action i Func, więc może ktoś bardziej doświadczony mógłby to rozgryźć.