Как обрабатывать ArgumentOutOfRangeException
У меня есть общий класс ListManager с методом, возвращающим объект по определенному индексу. Я проверяю, что индекс находится в пределах диапазона, чтобы избежать исключений. Что мне делать, если индекс находится вне диапазона? Я пытался вернуть ноль, но это невозможно. Я хотел бы сделать это без использования try catch. Какие-либо предложения?
public T GetAt<T>(int index)
{
if (index <= list.Count() - 1)
return list[index];
else
return null; //This will not compile
}
3 ответа
Ты мог бы вернуться default(T)
его null
для типов ссылок. Но для типов значений вы вернете некоторое значение по умолчанию, например, 0 для int. Возможно, это то, что вы хотите.
Ради возвращения null
когда индекс выходит за пределы диапазона, вы можете написать 2 версии для значений и ссылочных типов
public class ValMgr<T> where T : struct
{
public List<T> list;
public T? GetAt(int index, T? defv = null)
{
if (index < list.Count)
{
return list[index] as T?;
}
return defv;
}
}
А также
public class RefMgr<T> where T : class
{
public List<T> list;
public T GetAt(int index, T defv = null)
{
// don't reinvent the wheel
T ret = list.ElementAtOrDefault(index) as T;
return (ret == null) ? defv : ret;
}
}
Использование демо
var m = new ValMgr<int>();
m.list = new List<int>() { 1 };
var test1 = m.GetAt(0); // 1
var test2 = m.GetAt(1); // null
var test2bis = m.GetAt(1,-1); // -1
var n = new RefMgr<string>();
n.list = new List<string>() { "1" };
var test3 = n.GetAt(0); // "1"
var test4 = n.GetAt(1); // null
var test4bis = n.GetAt(1,"--"); // --
Но обратите внимание, что вы всегда можете использовать стандартный Linq ElementAtOrDefault, если вы просто хотите вернуть null
для справочных типов и default
значение для типов значений.
Как правило, с помощью такого общего метода вы хотите, чтобы вызывающая сторона знала, что они передали недопустимое значение в ваш метод. Так как тип не обнуляемый, правильное, что нужно сделать, это отправить исключение обратно вызывающей стороне. Вы можете просто оставить его в покое и позволить пузырю ArgumentOutOfRangeException вернуться к вызывающей стороне. Или, если вы хотите использовать собственный настраиваемый тип исключения или сообщение, вы должны перехватить ArgumentOutOfRangeException и создать свое собственное исключение, установив для Inner Exception исключение ArgumentOutOfRangeException, которое вы перехватили.
Если вы не хотите использовать try/catch, вы можете использовать существующую логику, но в части "else" создайте собственное исключение, без внутреннего исключения.
Единственный другой вариант - вернуть default(t), но я бы не рекомендовал это. Если вы сделаете это, то вызывающий метод не будет знать, что он пытался получить доступ к недопустимому значению, и может продолжить свой веселый путь, полагая, что возвращенное им значение по умолчанию (скажем, 0 для in int или false в case of bool) - это фактическое значение, хранимое по запрошенному индексу, что, скорее всего, приведет к ошибкам в их решении.