#c#
#c#
Вопрос:
В C#:
Возможно ли определить метод, входным параметром которого является любой метод?
Позвольте мне более подробное описание:
Я хочу метод с сигнатурой
bool IsDoit(var method)
{
try
{
method(...);
return true;
}
catch{return false;}
}
Это возвращает метод и логическое значение, которое вызывает исключение или нет!
Универсальный делегат? Общее действие? Общая функция?
У вас есть какие-либо идеи или это невозможно?
Комментарии:
1. Вместо bool возвращать объект исключения — лучшая идея
Ответ №1:
Что должно входить в «…» здесь? Похоже, вам нужен делегат с некоторым описанием — и сигнатура этого делегата должна соответствовать сигнатуре метода, который вы хотите вызвать. Например:
static bool IsDoit(Action method)
{
try
{
method();
return true;
}
catch
{
return false;
}
}
Это позволит преобразовать группу методов для любого метода void без параметров:
if (IsDoIt(SomeMethodWithNoParameters))
{
}
Если вызывающий хочет вызвать метод, который принимает другие параметры, они могут использовать лямбда-выражение, чтобы обернуть его в Action
:
if (IsDoIt(() => MethodWithParameters("first", "second"))
{
}
Лично я совсем не уверен в разумности этого дизайна в первую очередь, имейте в виду — перехват исключений и проглатывание их без какого-либо протоколирования кажется мне действительно плохой идеей.
Комментарии:
1. Я согласен с вами по поводу перехвата исключений и их проглатывания. Спасибо за вашу идею.
2. @RedHat: За исключением того, что это
Exception
уже ссылочный тип, поэтому вы не можете писатьNullable<Exception>
. Но я бы все равно обычно не поощрял это; идиоматический способ обработки исключений заключается в том, чтобы они выбрасывались, а не возвращались. Могут быть некоторые случаи, когда это уместно, но я бы предположил, что они довольно редки.
Ответ №2:
Да, для методов без параметров замените var
на Action
.
Ответ №3:
Вы можете передать свой метод как делегат, например, с помощью action:
bool IsDoit(Action test)
{
test(...);
}
Ответ №4:
Вы всегда можете принять универсальный делегат. Все делегаты являются производными от System.Делегировать
using System;
public class Program
{
public delegate R Deleg1<R,T1>(T1 arg);
public delegate R Deleg2<R,T1,T2>(T1 arg1, T2 arg2);
public delegate R Deleg3<R,T1,T2,T3>(T1 arg1, T2 arg2, T3 arg3);
public static void AcceptAny<R,T1>(Deleg1<R,T1> del) { /**/ }
public static void AcceptAny<R,T1,T2>(Deleg2<R,T1,T2> del) { /**/ }
public static void AcceptAny<R,T1,T2,T3>(Deleg3<R,T1,T2,T3> del) { /**/ }
public static void Main(string[] args)
{
}
}
Если вы не возражаете против небольшого удаления текста, вы можете
public delegate R DelegParams<R>(params object[] @params);
public static void AcceptAny<R>(DelegParams<R> paramsFunc) { /**/ }
Вы можете косвенно назначить практически любой делегат для этой подписи, используя для ее переноса лямбда-выражение (очень похоже на Action
подход, показанный Джоном Скитом).
Обратите внимание, что делегаты используют общий базовый класс и позволяют вызывать их с использованием интерфейсов, подобных отражению (например, используя общие object[]
параметры): Delegate.Метод DynamicInvoke