Перегруженный метод вызывает перегруженный метод - PullRequest
3 голосов
/ 08 января 2009

У меня есть метод, который я пишу, который вызывает внутри него другой перегруженный метод. Я хотел бы написать только один внешний метод, так как параметр внешнего метода передается внутреннему. Есть ли способ сделать это?

Я пытался использовать дженерики, но я недостаточно знаю об этом, поэтому он не работает:

public void OuterMethod<T>(T parameter)
{
    InnerMethod(parameter); // InnerMethod accepts an int or a string
}

Я знаю, что могу сделать это:

public void OuterMethod(string parameter)
{
    InnerMethod(parameter);
}

public void OuterMethod(int parameter)
{
    InnerMethod(parameter);
}

Но я бы предпочел сделать это правильно вместо копирования / вставки кода. Какой лучший способ сделать это?

Ответы [ 6 ]

4 голосов
/ 08 января 2009

Вы можете сделать это в C ++, но не в C # (если только внутренний метод не может быть универсальным, а не перегруженным).


В качестве альтернативы (если вы не ответите «нет»), вы можете переключить тип во время выполнения, как, например, ...

public void OuterMethod(object parameter)
{
    if (parameter is int)
        InnerMethod((int)parameter);
    else if (parameter is string)
        InnerMethod((string)parameter);
    else
        throw new SomeKindOfException();
}

... но, очевидно, это проверка во время выполнения, а не проверка во время компиляции.

Но я бы предпочел сделать это правильно вместо копирования / вставки кода.

Вы также можете написать программное обеспечение для написания ваших внешних методов (например, используя классы System.CodeDom) вместо того, чтобы писать их вручную, но это, вероятно, больше проблем, чем стоит.

2 голосов
/ 08 января 2009

Как сказали другие, вы не можете делать то, что пытаетесь сделать, и вариант, который вы указали в своем вопросе, - лучшая ставка.

На самом деле вам придется конвертировать значение, если вы используете универсальный. В противном случае вы можете унизиться, приняв Объект, как предлагает ChrisW.

 public void OuterMethod<T>(T parameter) 
            {
                T temp = parameter;
                if (temp is string )
                    InnerMethod(Convert.ToString(temp));
                if (temp is int)
                    InnerMethod(Convert.ToInt32(temp));// InnerMethod accepts an int or a string
            }

Вот ссылка на обзор Generics: http://msdn.microsoft.com/en-us/library/ms172193.aspx

1 голос
/ 01 декабря 2014

Вы можете использовать тип dynamic, чтобы отложить разрешение перегрузки до времени выполнения.

public void OuterMethod(dynamic parameter)
{
    InnerMethod(parameter);
}

public void InnerMethod(int parameter) { }
public void InnerMethod(string parameter) { }

Предостережение Выражения динамического типа не разрешены, или тип не проверен компилятором. Также может быть снижение производительности.

1 голос
/ 08 января 2009

Из вашего описания это выглядит как чрезмерная оптимизация.

Как насчет:

public void OuterMethod(string parameter)
{
    InnerMethod(parameter);
}

public void OuterMethod(int parameter)
{
    InnerMethod(parameter**.ToString()**);
}
0 голосов
/ 17 февраля 2009

Хорошо, у меня похожая ситуация, это метод контроля доступа в моей бизнес-логике.

Существует функция сохранения, которая может быть применена к любому из моих объектов слоя устойчивости.

так это выглядит так

public static Save<T>(AccessControl.User user,T entity) where T:PersistanceLayerBaseClass
{
    if(CanWrite(user, entity))
    {
        entity.save();
    }
    else
    {
        throw new Exception("Cannot Save");
    }
}

Как бы то ни было, у меня есть некоторый пользовательский код для определенных сущностей с точки зрения контроля доступа, поэтому я написал следующее: он ищет метод, более подходящий для вопроса, использующего System.Reflection, "может ли эта сущность быть написана этим пользователем?"

public static Boolean CanWrite<T>(AccessControl.User user, T entity) where T : PersistanceLayerBaseClass
        {
            int? clubId = null;
            MethodInfo methodInfo = entity.GetType().GetMethod("CanWrite", new Type[] { typeof(AccessControl.User), entity.GetType() });
            if(methodInfo != null)
            {
                return (Boolean)methodInfo.Invoke(null, new object[] { user, entity }) ;
            }
            else 
            {
                //generic answer
            }
            return HasRole(user.UserID, "Administrator") || (clubId.HasValue && user.MemberObject.ClubId == clubId.Value && HasRole(user.UserID, "AdministerClub"));
        }

Теперь каждый раз, когда я добавляю или удаляю метод, мне нужно только добавить или удалить его в одном месте

0 голосов
/ 08 января 2009

Если OuterMethod всегда вызывает InnerMethod, а InnerMethod принимает только int или строку, тогда OuterMethod не имеет никакого смысла.

Если разница только заключается в том, что один вызывает InnerMethod (int), а другой - InnerMethod (string), вы можете сделать что-то вроде этого:

public void OuterMethod(string parameter)
{
    InnerMethodA(parameter);
}

public void OuterMethod(int parameter)
{
    InnerMethodA(parameter);
}

private void InnerMethodA(object parameter)
{
    // Whatever other implementation stuff goes here

    if (parameter is string)
    {
        InnerMethodB((string) parameter);
    }
    else if (parameter is int)
    {
        InnerMethodB((string) parameter);
    }
    else
    {
        throw new ArgumentException(...);
    }
}

private void InnerMethodB(string parameter)
{
    // ...
}

private void InnerMethodB(int parameter)
{
    // ...
}
...