Перегруженный метод, вызывающий перегруженный метод

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

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

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);
}

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
0
2 557
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Ответ принят как подходящий

Вы можете сделать это на 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();
}

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

But I'd rather do this the right way instead of copying/pasting code.

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

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

Если разница Только заключается в том, что один вызывает 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)
{
    // ...
}

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

На самом деле вам придется преобразовать значение, если вы используете общий. В противном случае вы можете отказаться от него, приняв объект, как предлагает 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

Просто чтобы добавить, что для типов, допускающих значение NULL (строка, но не int), вы можете использовать ключевое слово «as» для преобразования.

Jacob Proffitt 08.01.2009 03:24

Вы сказали: «вы не можете распаковать его, как предлагает ChrisW» ... вы говорите, что не можете выполнить понижающее преобразование от объекта к int и / или от объекта к строке? Обратите внимание, что мой пример OuterMethod не является универсальным, и его параметр относится к типу object, а не к типу T.

ChrisW 09.01.2009 00:21

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

Как насчет:

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

public void OuterMethod(int parameter)
{
    InnerMethod(parameter**.ToString()**);
}

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

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

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

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"));
        }

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

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

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

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

ПредостережениеВыражения типа dynamic не разрешаются или тип не проверяется компилятором. И еще может быть потеря производительности.

Другие вопросы по теме