Да, я знаю, что буду выглядеть идиотом с этим, но мой мозг просто нет начинает работать сегодня утром.
Я хочу иметь метод, в котором я мог бы сказать: «Если что-то пойдет не так, вернитесь с этим типом исключения», верно?
Например, что-то вроде (и это не работает):
static ExType TestException<ExType>(string message) where ExType:Exception
{
Exception ex1 = new Exception();
ExType ex = new Exception(message);
return ex;
}
Теперь меня смущает то, что мы ЗНАТЬ, что общий тип будет иметь тип Exception из-за предложения куда. Однако код не работает, потому что мы не можем неявно преобразовать Исключение в ExType. Мы также не можем явно преобразовать его, например:
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 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);
}
Ваш второй фрагмент кода также не компилируется. Невозможно указать ограничение универсального типа, которое ожидает один строковый аргумент для конструктора.
Практически это можно сделать так:
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.
Это предполагает, что тип исключения имеет перегрузку конструктора с сигнатурой public ExceptionType (string message);. Обычно это так, но не всегда. Исключение составляет System.ArgumentOutOfRangeException. Первый строковый аргумент его конструктора - paramName, а не message. Что раздражает.
System.ArgumentNullException также имеет конструктор public ArgumentNullException (string paramName);
Единственная проблема с решением заключается в том, что можно создать подкласс 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");
Честно говоря, я думаю, что написание метода таким образом («если что-то пойдет не так, вернись с этим типом исключения») может оказаться слишком проблематичным по сравнению с крайними случаями (см. Мои комментарии ниже относительно типов исключений, где
message- нет первая строка arg), а также wrt (in) гибкость. Re. в последнем случае вы можете захотеть установить больше, чем сообщение об исключении, или использовать некоторые значения / переменные, которые хранятся только у вызывающего. Возможно, делегатAction, который может быть вызван для генерации исключения, может быть более подходящим во многих случаях?