У меня есть метод, который я пишу, который вызывает внутри него другой перегруженный метод. Я хотел бы написать только один внешний метод, поскольку параметр внешнего метода передается внутреннему. Есть ли способ сделать это?
Я пробовал использовать дженерики, но я недостаточно знаю об этом, поэтому он не работает:
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);
}
Но я бы предпочел сделать это правильно, а не копировать / вставлять код. Как лучше всего этого добиться?





Вы можете сделать это на 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
Вы сказали: «вы не можете распаковать его, как предлагает ChrisW» ... вы говорите, что не можете выполнить понижающее преобразование от объекта к int и / или от объекта к строке? Обратите внимание, что мой пример OuterMethod не является универсальным, и его параметр относится к типу object, а не к типу T.
Из вашего описания это кажется чрезмерной оптимизацией.
Как насчет:
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 не разрешаются или тип не проверяется компилятором. И еще может быть потеря производительности.
Просто чтобы добавить, что для типов, допускающих значение NULL (строка, но не int), вы можете использовать ключевое слово «as» для преобразования.