Просить общий метод бросить конкретный тип исключения на FAIL
Правильно, я знаю, что я полностью буду выглядеть идиотом с этим, но мой мозг просто не пинает сегодня утром.
Я хочу иметь метод, где я могу сказать "если это плохо, вернитесь с этим типом исключения", правильно?
Например, что-то вроде (и это не работает):
static ExType TestException<ExType>(string message) where ExType:Exception
{
Exception ex1 = new Exception();
ExType ex = new Exception(message);
return ex;
}
Теперь что нас смущает, так это то, что мы ЗНАЕМ, что общий тип будет иметь тип исключения из-за предложения where. Однако код выходит из строя, потому что мы не можем неявно использовать Exception для ExType. Мы также не можем его явно преобразовать, например:
static ExType TestException<ExType>(string message) where ExType:Exception
{
Exception ex1 = new Exception();
ExType ex = (ExType)(new Exception(message));
return ex;
}
Как это не удается... Так что возможно такое? У меня есть сильное чувство, что это будет очень просто, но у меня тяжелый день со старым ноггином, поэтому вырезать мне немного слабину: P
Update
Спасибо за ответы, ребята, похоже, что я не был полным идиотом!;)
ОК, поэтому Vegard и Сэм включил меня в точку, где я мог бы создать правильный тип, но затем явно застрял, потому что параметр сообщения доступен только для чтения после создания экземпляра.
Matt поразил гвоздь прямо на голове своим ответом, я протестировал это, и все работает отлично. Вот пример кода:
static ExType TestException<ExType>(string message) where ExType:Exception, new ()
{
ExType ex = (ExType)Activator.CreateInstance(typeof(ExType), message);
return ex;
}
Сладкое!:)
Спасибо, ребята!
Ответы
Ответ 1
Вы можете сделать это примерно так:
static void TestException<E>(string message) where E : Exception, new()
{
var e = new E();
e.Message = message;
throw e;
}
Однако это не компилируется, потому что Exception.Message только для чтения. Он может быть назначен только путем передачи его конструктору, и нет способа ограничить общий тип чем-то другим, кроме конструктора по умолчанию.
Я думаю, вам придется использовать отражение (Activator.CreateInstance) для "нового" настраиваемого типа исключения с параметром сообщения, например:
static void TestException<E>(string message) where E : Exception
{
throw Activator.CreateInstance(typeof(E), message) as E;
}
Изменить. К сожалению, вы поняли, что хотите вернуть исключение, а не бросать его. Тот же принцип применяется, поэтому я оставлю свой ответ как есть с заявлениями о выбросах.
Ответ 2
Единственная проблема с решением заключается в том, что можно создать подкласс Exception, который не реализует конструктор с одним строковым параметром, поэтому может быть выбрано исключение MethodMissingException.
static void TestException<E>(string message) where E : Exception, new()
{
try
{
return Activator.CreateInstance(typeof(E), message) as E;
}
catch(MissingMethodException ex)
{
return new E();
}
}
Ответ 3
Я создавал встроенный тип исключения, которое я хочу бросить, например:
if (ItemNameIsValid(ItemName, out errorMessage))
throw new KeyNotFoundException("Invalid name '" + ItemName + "': " + errorMessage);
if (null == MyArgument)
throw new ArgumentNullException("MyArgument is null");
Ответ 4
Попробовали ли вы:
static T TestException<Exception>(string message)
{}
потому что у меня возникает ощущение, что вложение общего ограничения не требуется, поскольку все бросающиеся исключения должны наследовать от System.Exception в любом случае.
Помните, что generics действительно принимают унаследованные типы.
Ответ 5
Я думаю, что все исключения должны иметь конструктор без параметров и иметь свойство Message
, поэтому следующее должно работать:
static ExType TestException<ExType>(string message) where ExType:Exception
{
ExType ex = new ExType();
ex.Message = message;
return ex;
}
Изменить: OK, сообщение только для чтения, поэтому вам нужно будет надеяться, что класс реализует конструктор Exception (string).
static ExType TestException<ExType>(string message) where ExType:Exception
{
return new ExType(message);
}