2015-11-04 1 views
-2

Название вопроса может быть не совсем понятным, но вот что я хочу сделать:Возможно ли перегрузить метод, основанный на другом методе?

Скажем, у меня есть статический класс A. Этот класс содержит статическую функцию, которая называется B. Он имеет 10+ перегрузок. Функция в значительной степени является базовой, несмотря на множество перегрузок; он не имеет ничего общего с другими членами класса. Я знаю, что могу получить к нему доступ из любой точки мира, импортируя правильные пространства имен и использование:

string bar = A.B("foo", true, 5) // Then do whatever with bar 

Теперь предположим, что у меня есть еще один класс C (не в A). Теперь я хочу сделать метод под названием D в C, который ведет себя так же, как A.B во всех отношениях. Я пробовал:

public static class C { 
    public static string D(string p1, bool p2, int p3) { 
     return A.B(p1, p2, p3); 
    } 
} 

Но перегружать этот метод D точно как A.B, что я должен делать? Должен ли я писать все отдельные перегрузки вручную или есть лучший способ?

+4

Если 'C.D'' ведет себя так же, как' A.B' во всех отношениях, то какая пинта 'C.D'? –

+0

Я знаю, что это бессмысленно, но только ради знания. Скажем, у меня есть пять вложенных классов (я не думаю, что когда-нибудь будет, но все же). Мне нужно будет получить к ним доступ через «AnIncredibleLargeName.AnotherBigName.AnotherSubClass.YetAnotherSubClass.FinallyTheMethod'. Поэтому, чтобы получить доступ к ним из 'C', я думал о создании метода' D', чтобы просто называть 'D'. –

+1

Я не точно следую, но статические методы не наследуются, поэтому нет механизма наследования или полиморфизма статических методов. –

ответ

3

Должен ли я написать все отдельные перегруженные вручную

Если вы хотите иметь перегрузку D для каждой перегрузки B, то да, вам придется сделать именно это.

+0

Да, я так думал, но каждая перегрузка D также будет вести себя так же, как соответствующая перегрузка B. Нет ли возможности даже тогда? –

+1

Или переместите все эти методы в интерфейс/класс, чтобы получить некоторую помощь компилятора – Machinarius

+0

@FarhanAnam Там нет языковой поддержки, которая позволила бы вам избежать этого. Вы можете написать свой собственный инструмент генерации кода (или найти сторонний инструмент), чтобы сгенерировать этот код для вас, но код все равно нужно будет каким-то образом записать. – Servy

-3

Это хороший пример недостатков статических методов.

Если вы можете, преобразовать эти статические методы в методы экземпляра (возможно, из какого-либо нового рабочего класса со статическим заводским методом для возврата экземпляра или использовать IOC). Тогда у вас будет гораздо больше возможностей использовать наследование, чтобы избежать повторения кода.

UPDATE

После некоторой обратной связи, я был думать и это возможно, вид. Используйте отражение, чтобы получить список параметров для всех версий B, и сравнить с списке параметров D.

public static int D(params object[] paramArray) 
{ 
    var paramTypes = paramArray.Select(x => x.GetType()); 
    var method = typeof(Static.A).GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy) 
     .Where(m => m.Name == "B" && m.GetParameters().Select(x => x.ParameterType).SequenceEqual(paramTypes)) 
     .FirstOrDefault(); 
    if (method != null) 
    { 
     return (int)method.Invoke(null, paramArray); 
    } 
    throw new Exception("Overloaded method not found"); 
} 

Недостатком этого подхода является то, что нет проверки параметров времени компиляции, нет Intellisense, и т.д. Я не могу придумать способ обхода этого, не повторяя спецификацию каждой версии A.B(), как это:

private static int GenericD(object[] paramArray, MethodBase caller) 
    { 
     var paramTypes = caller.GetParameters().Select(x => x.ParameterType); 
     var method = typeof(Static.A).GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy) 
      .Where(m => m.Name == "B" && m.GetParameters().Select(x => x.ParameterType).SequenceEqual(paramTypes)) 
      .FirstOrDefault(); 
     if (method != null) 
     { 
      return (int)method.Invoke(null, paramArray); 
     } 
     throw new Exception("Overloaded method not found"); 
    } 

    public static int D(string p) 
    { 
     object[] paramArray = new object[] { p }; 
     return GenericD(paramArray, MethodInfo.GetCurrentMethod()); 
    } 

    public static int D(string p, int x) 
    { 
     object[] paramArray = new object[] { p, x }; 
     return GenericD(paramArray, MethodInfo.GetCurrentMethod()); 
    } 

в этом решении, каждая версия D() практически идентична, но не вполне. В идеале вам нужен какой-то способ программной конвертации списка параметров метода в object[], но there doesn't seem to be an easy way to do that.

+0

У вас не возник вопрос, который я боюсь. –

+0

Я понял, что ваш вопрос будет о том, как избежать повторения фрагмента кода. Я указал, что ваши варианты избегать повторения себя ограничены, если вы используете статические методы/классы. Есть ли какая-то особая причина, по которой вы выбрали статический класс класса A или использовать вложенные классы? – mikeagg

+0

Я не могу отредактировать 'A'. Это класс из другой библиотеки. –

-1

Почему бы не сделать базовый метод методом расширения с общим типом, а затем просто реализовать любую специфичную для конкретного типа логику в одном методе расширения?

+0

Почему бы не перестать отвечать, не зная, что это не вопрос оптимизации кода. –

+0

Я думал, что этот вопрос связан с тем, как использовать статические методы повторяемым образом. Использование методов расширения с помощью дженериков - самый простой способ реализовать повторяемые методы. Речь идет не о оптимизации кода, а о понимании статики, расширений и основ перегрузки. –

+0

Хорошо, но не ясно ли из последних двух строк моего вопроса? –

Смежные вопросы