Это хорошая идея, чтобы создать пользовательское исключение, которое я ожидаю обработать? - PullRequest
2 голосов
/ 11 декабря 2010

Является ли хорошей идеей создать пользовательское исключение, которое будет выдаваться при сбое логики приложения, которая, как ожидается, будет обработана?

Лучше вернуть объект или значение, я думаю; но:

Если не , то каковы правильные условия для введения некоторых пользовательских исключений в наш код?

Спасибо!

Ответы [ 6 ]

7 голосов
/ 11 декабря 2010

Да, если предположить, что проблема, для которой вы хотите ее создать, действительно исключительная ситуация (т. Е. Должна случаться редко, если вообще когда-либо).

Если это нормальное состояние ошибки (то, что вы ожидаете, будет происходить регулярно и является частью обычного использования приложения), вы должны явным образом его кодировать - в этом случае, создавая и выбрасывание пользовательского исключения является запахом кода.

Кроме того, пользовательское исключение можно создавать только в том случае, если оно добавляет информацию (поверх встроенных).


Редактировать: (следующие комментарии)

Использование обработки исключений в качестве формы управления потоком (т. Е. Правильно ли завершена функция X) всегда - плохая идея и определенный запах кода.

1 голос
/ 11 декабря 2010

Лучше всего писать код без возможности создания исключений.Если вам нужна причина: они медленные.В большинстве случаев значительно медленнее, чем кодирование вокруг них даже самыми неэкранированными способами.При этом иногда они неизбежны из-за кода, написанного другими людьми, или они желательны, потому что вы действительно хотите, чтобы программа взорвалась перед лицом пользователя (см. Катастрофический сбой).Только в этих двух случаях исключение обрабатывает путь.

Но это не означает, что вы упаковываете каждую IEnumerable<T>.First() в if(sequence.Count() > 0).Научитесь правильно структурировать свой код, чтобы вы никогда не вызывали .First() в пустой последовательности.Элегантный код - это победа.

Недавно я написал быстрое приложение для моего работодателя для использования в автоматизированной системе (где пользователь не садится за клавиатуру), которое должно требовать от пользователявведите информацию для входа в систему в командной строке args (Think Batch File) или в конфигурационном файле, иначе она намеренно взорвется им в лицо, согласно спецификации.В этом случае исключение является оправданным.

Весь код ниже демонстрирует мою философию Исключений.

    private static string _password;
    public static string Password
    {
        get
        {
            if (_password.IsNullOrWhiteSpace())
                throw new NullReferenceException(string.Format("{0} {1}",
                    "Password was neither found in the .cfg file nor the",
                    "command line arguments."));
            return _password;
        }
        set
        {
            _password = value ?? string.Empty;
        }
    }

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

    public static bool All<T>(this IEnumerable<T> list, Func<T, T, bool> func)
    {
        if (list.Count() < 2)
            return true;

        T first = list.First();

        return list.Skip(1).Aggregate(true, (i, k) => i && func(first,k));
    }

Примечание нижеЯ имел дело с исключениями ввода / вывода в рамках метода ввода / вывода, но я проанализировал данные в файле конфигурации таким образом, что логика my никогда не вызовет исключения.Обратите внимание, как .Count () проверяется на 2 во всех фрагментах данных.На данный момент я могу быть уверен, что .First () и .Last () будут не только действительны для компилятора и не будут генерировать исключения, но и будут гарантированно давать потенциально допустимые фрагменты данных (без пробелов, разные значения).Эту философию я рекомендую вам адаптировать, когда вы думаете об обработке исключений -> Как отфильтровать и контролировать свои данные прозрачным способом, чтобы полностью устранить ошибки в рамках метода?

public static class ConfigParser
{
    public static Dictionary<string, string> PullFromConfigFile()
    {
        ParallelQuery<Tuple<string, string>> data;

        try
        {
            TextReader tr = new StreamReader("config.cfg");

            data = tr.ReadToEnd()
                .Split('\n')
                .AsParallel()

                .Select(i => new string(i.TakeWhile(k => k != '#').ToArray()))
                .Where(i => !i.IsNullOrWhiteSpace())

                .Select(i => i.Split('\t')
                    .Where(k => !k.IsNullOrWhiteSpace())
                    .Select(k => k.Trim())
                )
                .Where(i => i.Count() == 2)
                .Select(i => new Tuple<string, string>(i.First(), i.Last()));

            tr.Close();
        }
        catch (IOException)
        {
            Logger.Bad("config.cfg file was not found");
            return new Dictionary<string, string>();
        }
        return ConfigParser.ParseIntoDict(data);
    }

    private static Dictionary<string, string> ParseIntoDict(ParallelQuery<Tuple<string, string>> data)
    {
        var agg = new Dictionary<string, string>();
        foreach (var entry in data)
        {
            if (!agg.ContainsKey(entry.Item1))
                agg.Add(entry.Item1, entry.Item2);
        }

        var width = agg.Keys.Max(k => k.Length);
        agg.ForAll(i => Logger.Log("Loaded Data: {0} {1}",
            i.Key.SetWidth(width, '-'), i.Value));

        return agg;
    }
}

Используемые расширения:

public static class Extensions
{
    public static string SetWidth(this string item, int width, char padder, bool right = true)
    {
        if (item == null)
            return new string(padder, width);

        if (width > item.Length)
            return right ? item.PadRight(width, padder) : item.PadLeft(width, padder);
        return item.Substring(0, width);
    }
    public static bool IsNullOrWhiteSpace(this string str)
    {
        return string.IsNullOrWhiteSpace(str);
    }
}
1 голос
/ 11 декабря 2010

Обычно вы можете обойтись со стандартными исключениями.Если вы хотите предоставить более полезную информацию об отладке, вам могут помочь вспомогательные средства.

Вы хотите создавать свои собственные исключения, когда хотите предоставить информацию, выходящую за рамки того, что дают другие опции, или когда вы хотите, чтобы пользовательбыть в состоянии справиться с этим уникальным образом.Если все, что вы делаете, это упоминаете, что существует исключительная ситуация, тогда просто используйте колесо, которое уже есть, для использования.

Я предлагаю всегда наследовать от std :: exception или одного из его производных.

1 голос
/ 11 декабря 2010

Вы должны создавать свои собственные пользовательские исключения, когда ожидаете выполнить действие в зависимости от типа создаваемого исключения. Если ваша цель - показать пользователю сообщение, то тип создаваемого исключения означает очень мало.

Однако вы должны быть осторожны, когда создаете свои собственные типы исключений, поскольку в платформе .NET уже есть много очень хороших типов исключений, и вы должны сначала использовать один из них. Гораздо лучше иметь исключение FileNotFound, а не исключение JoesBestFileNotFound.

0 голосов
/ 11 декабря 2010

Если вы посмотрите на .NET FW, существует множество Exceptions для указания определенных условий. IndexOutOfBoundsException, NotImplementedException и т. Д. Все они существуют и основаны на исключениях для исключительных (не предусмотренных) случаев.

Проведение грани между тем, что следует классифицировать как Исключение, и простым возвратом нуля, например, часто может стать серым. Используйте свое лучшее суждение и постарайтесь оставаться неизменным в команде на этом суждении.

0 голосов
/ 11 декабря 2010

Как правило, вы не должны использовать исключения для нормальной логики программы.Однако вполне нормально создавать исключения для сценариев, специфичных для вашего приложения.Существует множество полезных советов по обработке исключений, например, Руководство по разработке исключений MSDN Документ для начинающих.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...