Запрос универсального метода для выдачи определенного типа исключения при FAIL
Вопрос
Да, я знаю, что буду выглядеть идиотом в этом случае, но мой мозг просто нет этим утром приступаю к работе.
Я хочу иметь метод, позволяющий сказать: «Если что-то пойдет не так, вернитесь с этим типом исключения», верно?
Например, что-то вроде (и это не работает):
static ExType TestException<ExType>(string message) where ExType:Exception
{
Exception ex1 = new Exception();
ExType ex = new Exception(message);
return ex;
}
Что меня смущает, так это то, что мы ЗНАТЬ что универсальный тип будет относиться к типу Exception из-за где пункт.Однако код терпит неудачу, потому что мы не можем неявно привести Исключение к ЭксТип.Мы также не можем явно преобразовать его, например:
static ExType TestException<ExType>(string message) where ExType:Exception
{
Exception ex1 = new Exception();
ExType ex = (ExType)(new Exception(message));
return ex;
}
Так как это тоже не получается..Так возможно ли такое? У меня твердое предчувствие, что это будет очень просто, но у меня тяжелый день со старой башкой, так что расслабьтесь :P
Обновлять
Спасибо за ответы ребята, похоже это не я был полный идиот!;)
Итак Вегард и Сэм подвел меня к моменту, когда я мог создать экземпляр правильного типа, но затем, очевидно, застрял, потому что сообщение После создания экземпляра параметр доступен только для чтения.
Мэтт Его ответ попал прямо в точку, я проверил это, и все работает нормально.Вот пример кода:
static ExType TestException<ExType>(string message) where ExType:Exception, new ()
{
ExType ex = (ExType)Activator.CreateInstance(typeof(ExType), message);
return ex;
}
Сладкий!:)
Спасибо ребята!
Решение
Вы можете сделать это примерно так:
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;
}
Редактировать Упс, только что понял, что ты хочешь возвращаться исключение, а не выбрасывать его.Применяется тот же принцип, поэтому я оставлю свой ответ без изменений с операторами throw.
Другие советы
Единственная проблема с решением заключается в том, что можно создать подкласс 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();
}
}
Я создал экземпляр типа исключения, которое хочу выбросить, например:
if (ItemNameIsValid(ItemName, out errorMessage))
throw new KeyNotFoundException("Invalid name '" + ItemName + "': " + errorMessage);
if (null == MyArgument)
throw new ArgumentNullException("MyArgument is null");
Вы пробовали вместо этого:
static T TestException<Exception>(string message)
{}
потому что у меня такое ощущение, что введение общего ограничения не требуется, поскольку все выбрасываемые исключения должен в любом случае наследовать от System.Exception.
Помните, что дженерики принимают унаследованные типы.
Я думаю, что все исключения должны иметь конструктор без параметров и иметь Message
свойство, поэтому должно работать следующее:
static ExType TestException<ExType>(string message) where ExType:Exception
{
ExType ex = new ExType();
ex.Message = message;
return ex;
}
Редактировать:Хорошо, сообщение доступно только для чтения, поэтому вам придется надеяться, что вместо этого класс реализует конструктор Exception(string).
static ExType TestException<ExType>(string message) where ExType:Exception
{
return new ExType(message);
}