Запрос универсального метода для выдачи определенного типа исключения в случае неудачи

Да, я знаю, что буду выглядеть идиотом с этим, но мой мозг просто нет начинает работать сегодня утром.

Я хочу иметь метод, в котором я мог бы сказать: «Если что-то пойдет не так, вернитесь с этим типом исключения», верно?

Например, что-то вроде (и это не работает):

    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;
    }

Милая! :)

Спасибо, парни!

Честно говоря, я думаю, что написание метода таким образом («если что-то пойдет не так, вернись с этим типом исключения») может оказаться слишком проблематичным по сравнению с крайними случаями (см. Мои комментарии ниже относительно типов исключений, где message - нет первая строка arg), а также wrt (in) гибкость. Re. в последнем случае вы можете захотеть установить больше, чем сообщение об исключении, или использовать некоторые значения / переменные, которые хранятся только у вызывающего. Возможно, делегат Action, который может быть вызван для генерации исключения, может быть более подходящим во многих случаях?

Andrew Webb 31.01.2019 17:43
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
11
1
5 691
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Вы пробовали вместо этого:

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);
}

Ваш второй фрагмент кода также не компилируется. Невозможно указать ограничение универсального типа, которое ожидает один строковый аргумент для конструктора.

cremor 09.08.2017 16:50
Ответ принят как подходящий

Практически это можно сделать так:

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. Что раздражает.

Andrew Webb 31.01.2019 17:29

System.ArgumentNullException также имеет конструктор public ArgumentNullException (string paramName);

Andrew Webb 31.01.2019 17:36

Единственная проблема с решением заключается в том, что можно создать подкласс 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");

Другие вопросы по теме