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