切换导航
简历
工具
演示
查询
导航菜单
服务端
30
前端
114
数据库
82
进阶开发
8
桌面程序
2
QA
15
软件使用
36
规范协议
5
操作系统
11
AI
0
复用资源
6
硬件
0
标签
C# 基础
Mybatis
ADO.NET
ASP.NET
Python 基础
Linq
Web Forms
.NET
Spring
SpringBoot
SpringCloud
.NET Core 中间件
Maven
.NET 类库
ASP.NET MVC
EF
NHibernate
WebApi
Java
外部链接
.NET Core SDK和运行时安装包
淘宝 NPM 镜像
查询网
Tables Generator线上表格转换工具
引用cdn在线脚本和样式
首页
服务端
System.Runtime 程序集 的异常处理 ArgumentOutOfRangeException 类
[TOC] ## 1. ArgumentOutOfRangeException 类 ### 1.1. 定义 |命名空间|程序集| |--|--| |System|System.Runtime.dll| **定义:**当自变量的值超出了所调用方法定义的允许值范围时引发的异常 **继承:**Object -》Exception -》SystemException -》ArgumentException -》ArgumentOutOfRangeException **抛出异常示例:** ```csharp public class ArgumentOutOfRange { public int size = 10; public ArgumentOutOfRange(int _size) { if (size < _size) { throw new ArgumentOutOfRangeException(nameof(size), _size, $"初始化值超出范围,只能是小于10的整数"); } else { size = _size; } } public int Size { get => size; set => size = value; } } static public string Example() { try { ArgumentOutOfRange a = new ArgumentOutOfRange(20); msg = a.Size.ToString(); } catch (ArgumentOutOfRangeException e) { msg = $"ErrorInfo:{e.Message},Value:{e.ActualValue}"; } return msg; } ``` > Tips:调用方法并且传递给方法的参数中至少有一个不是null,并且包含无效值(该值不是参数预期值集的成员)时,将引发异常。 属性 ParamName 标识无效参数,如果存在值,则 ActualValue 属性标识无效值。 ### 1.2. 构造函数 ArgumentOutOfRangeException 有五个构造函数,造函数将 Message 新实例的 属性初始化为描述错误的系统提供的消息,例如“需要非反数”。此消息考虑了当前系统区域性。 #### 1.2.1. 无参构造函数 **构造函数:**<mark>public ArgumentOutOfRangeException ()</mark> 下表显示了 ArgumentOutOfRangeException 实例的初始属性值。 |属性|值| |--|--| |InnerException|空引用(在 Visual Basic 中为 Nothing)。| |Message|本地化的错误消息字符串。| #### 1.2.2. 一个参数的构造函数 **构造函数:**<mark>ArgumentOutOfRangeException(String)</mark> |参数|说明| |--|--| |paramName[String]|此构造函数用 ParamName 参数初始化新实例的 paramName 属性。 paramName 的内容设计为易于理解。| 下表显示了 ArgumentOutOfRangeException 实例的初始属性值。 |属性|值| |--|--| |InnerException|空引用(在 Visual Basic 中为 Nothing)| |Message|空字符串 (“”) | |ParamName|参数名称字符串| #### 1.2.3. 二个参数的构造函数 **构造函数:**<mark>public ArgumentOutOfRangeException (string? message, Exception? innerException);</mark> |参数|说明| |--|--| |message[String]|说明发生此异常的原因的错误消息| |innerException[Exception]|导致当前异常的异常;如果未指定内部异常,则是一个 null 引用(在 Visual Basic 中为 Nothing)| #### 1.2.4. 二个参数的构造函数 **构造函数:**<mark>public ArgumentOutOfRangeException (string? paramName, string? message);</mark>, 此构造函数用 ParamName 参数初始化新实例的 paramName 属性。 paramName 的内容设计为易于理解。 |参数|说明| |--|--| |paramName[String]|导致异常的参数的名称| |message[String]|描述错误的消息| 下表显示了 ArgumentOutOfRangeException 实例的初始属性值。 |属性|值| |--|--| |InnerException|null| |Message|错误消息字符串| |ParamName|参数名称字符串| #### 1.2.5. 三个参数的构造函数 **构造函数:**<mark>public ArgumentOutOfRangeException (string? paramName, object? actualValue, string? message);</mark> |参数|说明| |--|--| |paramName[String]|导致异常的参数的名称| |actualValue[Object]|导致此异常的参数值| |message[String]|描述错误的消息| **注解** 此构造函数使用 参数初始化ParamName新实例的 属性,ActualValue使用 actualValue 参数初始化 属性,Message并使用 参数初始化 message 属性。paramName 和 message 参数的内容paramName旨在由人类理解。 需要此构造函数的调用方来确保这些字符串已针对当前系统区域性进行了本地化。 参数 actualValue 不在 .NET 类库中使用。 但是,应用可以使用 ActualValue 属性来获取可用的参数值。 参数 actualValue 包含传递给 方法并导致引发此异常的无效值。 此值存储在 属性中, ActualValue 其字符串表示形式追加到 属性中 Message 保存的消息字符串。 下表显示了 ArgumentOutOfRangeException 实例的初始属性值。 |属性|值| |--|--| |ActualValue|参数值| |InnerException|Visual Basic Nothing 中的 null 引用 | |Message|错误消息字符串| |ParamName|参数名称字符串| ### 1.3. 属性 |属性|说明| |--|--| |ActualValue|获取导致此异常的参数值| |Data|获取键/值对的集合,这些键/值对提供有关该异常的其他用户定义信息<br>(继承自 Exception)| |HelpLink|获取或设置指向与此异常关联的帮助文件链接<br>(继承自 Exception)| |HResult|获取或设置 HRESULT(一个分配给特定异常的编码数字值)<br>(继承自 Exception)| |InnerException|获取导致当前异常的 Exception 实例<br>(继承自 Exception)| |[Message](https://learn.microsoft.com/zh-cn/dotnet/api/system.argumentoutofrangeexception.message?view=net-8.0#system-argumentoutofrangeexception-message)|**作用:**获取错误消息和无效参数值的字符串表示形式;或者,如果该参数值为 null,则仅获取错误消息。<br>**声明:**<mark>public override string Message { get; }</mark><br><small>actualValue 为 null。传递到构造函数的 message 字符串<br>actualValue 不为 null。附有无效参数值字符串表示形式的 message 字符串</small>| |ParamName|获取导致该异常的参数的名称<br>(继承自 ArgumentException)| |Source|获取或设置导致错误的应用程序或对象的名称<br>(继承自 Exception)| |StackTrace|获取调用堆栈上的即时框架字符串表示形式<br>(继承自 Exception)| |TargetSite|获取引发当前异常的方法<br>(继承自 Exception)| ### 1.4. 方法 |方法|说明| | --| -- | |Equals(Object)|确定指定对象是否等于当前对象<br>(继承自 Object)| |GetBaseException()|当在派生类中重写时,返回 Exception,它是一个或多个并发的异常的根本原因<br>(继承自 Exception)| |GetHashCode()|作为默认哈希函数<br>(继承自 Object)| |GetObjectData(SerializationInfo, StreamingContext)|已过时<br>设置带有无效参数值和附加异常信息的 SerializationInfo 对象| |GetType()|获取当前实例的运行时类型<br>(继承自 Exception)| |MemberwiseClone()|创建当前 Object 的浅表副本<br>(继承自 Object)| |`ThrowIfEqual<T>(T, T, String)`|如果 等于 other,则valueArgumentOutOfRangeException引发| |`ThrowIfGreaterThan<T>(T, T, String)`|如果 value 大于 other,则ArgumentOutOfRangeException引发| |`ThrowIfGreaterThanOrEqual<T>(T, T, String)`|如果 value 大于或等于 other,则ArgumentOutOfRangeException引发 。| |`ThrowIfLessThan<T>(T, T, String)`|如果 value 小于 other,则ArgumentOutOfRangeException引发| |`ThrowIfLessThanOrEqual<T>(T, T, String)`|如果 value 小于或等于 ,other则ArgumentOutOfRangeException引发| |`ThrowIfNegative<T>(T, String)`|如果 value 为负值,ArgumentOutOfRangeException则引发| |`ThrowIfNegativeOrZero<T>(T, String)`|如果 为负数或零,则ArgumentOutOfRangeExceptionvalue引发| |`ThrowIfNotEqual<T>(T, T, String)`|如果 不等于 other,则ArgumentOutOfRangeExceptionvalue引发| |`ThrowIfZero<T>(T, String)`|如果 value 为零,则ArgumentOutOfRangeException引发| |ToString()|创建并返回当前异常的字符串表示形式<br>(继承自 Exception)| ### 1.5. 适用于 |产品|版本| |--|--| |.NET|Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8| |.NET Framework|1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1| |.NET Standard|1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 2.0, 2.1| |UWP|10.0| ### 1.6. 经常使用场景 ArgumentOutOfRangeException 被广泛使用:【System.IO 命名空间中的System.Collections类】、【Array 类】、【类中的 String 字符串操作方法】 > Tips:过时写法未记录,例如事件和一个2个对象参数的构造函数 ## 2. 常见引发异常的条件 ### 2.1. 按集合的索引号检索该成员,并且索引号无效 这是导致异常的 ArgumentOutOfRangeException 最常见原因。 通常,索引号无效有以下四个原因之一 #### 2.1.1. 尝试从没有数据的集合中取值 ```csharp public static string Example1() { var list = new List<string>(); try { msg = $"The first item: '{list[0]}'"; } catch (ArgumentOutOfRangeException e) { msg = e.Message; // Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'index') // 索引超出范围。必须是非负的并且小于集合的大小。 } return msg; } ``` #### 2.1.2. 使用不存在的索引 ```csharp public static string Example2() { try { var list = new List<string>(); list.AddRange(new string[] { "曹操", "刘备", "孙权", "袁绍", }); var newList = new List<string>(); for (int i = 0; i < list.Count; i++) { newList[i] = list[i]; } msg = string.Join(",", newList.ToArray()); } catch (ArgumentOutOfRangeException e) { msg += e.Message; } return msg; } ``` > Tips:上述代码会异常,异常信息是:Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'index') 修正上面的代码只要将索引添加方式修改为Add方法即可,newList[i] = list[i]; =》newList.Add(list[i]); #### 2.1.3. 索引为负数 ```csharp public static string Example() { try { var list = new List<string>(); list.AddRange(new string[] { "曹操", "刘备", "孙权", "袁绍", }); int index = list.FindIndex((s) => s.Equals("董卓", StringComparison.InvariantCulture)); // 上面的index将为-1 msg = $"Index {0} contains '{index}',{list[index]}"; } catch (ArgumentOutOfRangeException e) { msg = e.Message; } return msg; } ``` > **Tips:**上述示例中,通过 FindIndex 函数去找一个不存在的值,不存在则返回负数,然后 list[index] 就是一个索引为负数的写法,这里便会报错,错误信息:<mark>Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'index')【索引超出范围。必须是非负的并且小于集合的大小】</mark> #### 2.1.4. 索引值为集合的Count时 ```csharp public static string Example() { try { var list = new List<string>(); list.AddRange(new string[] { "曹操", "刘备", "孙权", "袁绍", }); msg = $"最后一个成员{list[list.Count]}"; // Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'index') } catch (ArgumentOutOfRangeException e) { msg = e.Message; } return msg; } ``` > **Tips:**索引是从0开始的,但集合Count是当前集合的数量,是从1开始的,因此使用索引获取集合的最后一个成员需要使用 list[list.Count-1] ### 2.2. 调用字符串操作方法执行字符串操作,并且字符串中不存在起始索引 用于指定操作`起始索引`的方法的重载要求索引在字符串中是有效位置。 String.CompareOrdinal 有效索引范围为 0 到 String.Length - 1 #### 2.2.1. 空字符串索引为0 使用空字符串或 String.Empty。 由于其 String.Length 属性返回 0,因此任何通过索引操作它的尝试都将IndexOutOfRangeException 引发异常 ```csharp public static string Example() { try { string[] words = { "曹操", "刘备", "孙权", "袁绍", " ", "" }; foreach (var word in words) msg += $"首位字符 {word}: {word[0]} \n"; } catch (IndexOutOfRangeException e) { msg = e.Message; // Index was outside the bounds of the array. } return msg; } ``` > **Tips:**上面的示例引起的异常并不是 ArgumentOutOfRangeException,而是 IndexOutOfRangeException #### 2.2.2. 包含字符串所在位置做操作 根据子字符串在该字符串中的位置操作字符串,但无法确定是否实际找到该子字符串 ```csharp public static string Example() { try { string[] words = { "曹操 孟德", "刘备 玄德", "孙权 仲谋", "袁本初" }; foreach (var word in words) msg += $"首位字符 {word}: {word.Substring(word.IndexOf(" "))} \n"; } catch (ArgumentOutOfRangeException e) { msg = e.Message; // StartIndex cannot be less than zero. (Parameter 'startIndex') } return msg; } ``` > **Tips:**上面示例根据字符串中的空格字符来截取字符串,因为最后一个字符串没有空格,IndexOf(" ") 返回-1,从而导致错误,改进只要判断 IndexOf(" ") 大于0即可 #### 2.2.3. 截取字符串超出字符串长度 ```csharp public static string Example() { try { string info = "东汉末年分三国,魏、蜀、吴"; int index = info.IndexOf(','); // msg = info.Substring(index, info.Length - 1); // 错误 msg = info.Substring(index, info.Length - index); // 正确 } catch (ArgumentOutOfRangeException e) { msg = e.Message; // StartIndex cannot be less than zero. (Parameter 'startIndex') } return msg; } ``` > **Tips:**String.Substring方法第二参数是要截取的长度,上面错误的代码,从起始的位置加上整个字符串的长度明显超出了范围,因此就会进入到 ArgumentOutOfRangeException 异常中 ### 2.3. 将负数传递给需要是自然数为参数的方法 ```csharp public static string Example8() { try { Array.CreateInstance(typeof(string), 10, -2); } catch (ArgumentOutOfRangeException e) { msg = e.Message; // Non-negative number required. (Parameter 'length2') } return msg; } ``` > **Tips:** Array.CreateInstance 方法参数需要的都是大于等于0的自然数,示例中传入一个-2因此进入到异常中,只要将参数都改为自然数即可 ### 2.4. 争用集合时冲突 多线程应用或具有异步执行的任务以及更新数组或集合的应用中存在争用条件 ```csharp static List<Continent> continents = new List<Continent>(); static string? s_msg; public static string Example() { String[] names = { "Africa", "Antarctica", "Asia", "Australia", "Europe", "North America", "South America" }; // Populate the list. foreach (var name in names) { var th = new Thread(PopulateContinents); th.Start(name); } Console.WriteLine(s_msg); Console.WriteLine(); // Display the list. for (int ctr = 0; ctr < names.Length; ctr++) { var continent = continents[ctr]; // System.ArgumentOutOfRangeException:“Index was out of range. Must be non-negative and less than the size of the collection. Arg_ParamName_Name” Console.WriteLine("{0}: Area: {1}, Population {2}", continent.Name, continent.Population, continent.Area); } return msg; } private static void PopulateContinents(Object? obj) { string? name = obj?.ToString(); s_msg += string.Format("Adding '{0}' to the list.\n", name); var continent = new Continent(); continent.Name = name; // Sleep to simulate retrieving remaining data. Thread.Sleep(50); continents.Add(continent); } ``` > **Tips:** 上述代码抛出 ArgumentOutOfRangeException 异常的原因就是多线程执行下,子线程没有执行完,主线程执行到集合了取数,这时的集合并没有填充完毕,因此使用大于集合数量的索引去取值时就会显示超出范围的异常,改进的方式就是要让子线程都执行完后再继续执行主线程,改进后示例代码如下 ```csharp static ConcurrentBag<ContinentD> ContinentDs = new ConcurrentBag<ContinentD>(); static CountdownEvent? gate; static string msg = string.Empty; public static void Example() { String[] names = { "Africa", "Antarctica", "Asia", "Australia", "Europe", "North America", "South America" }; gate = new CountdownEvent(names.Length); // Populate the list. foreach (var name in names) { var th = new Thread(PopulateContinentDs); th.Start(name); } // Display the list. gate.Wait(); Console.WriteLine(msg); Console.WriteLine(); var arr = ContinentDs.ToArray(); for (int ctr = 0; ctr < names.Length; ctr++) { var ContinentD = arr[ctr]; Console.WriteLine("{0}: Area: {1}, Population {2}", ContinentD.Name, ContinentD.Population, ContinentD.Area); } } private static void PopulateContinentDs(Object? obj) { string? name = obj?.ToString(); lock(msg) { msg += string.Format("Adding '{0}' to the list.\n", name); } var ContinentD = new ContinentD(); ContinentD.Name = name; // Sleep to simulate retrieving remaining data. Thread.Sleep(25); ContinentDs.Add(ContinentD); gate?.Signal(); } ``` [========] > 参考资料: [《ArgumentOutOfRangeException 类》](https://learn.microsoft.com/zh-cn/dotnet/api/system.argumentoutofrangeexception?view=net-8.0#code-try-3)
扫一扫手机看
点击排行
windows 文件资源管理器使用
Layui 弹窗open使用说明
SQL Server 中字符串函数使用
C# 使用QQ邮箱代理做邮件接收功能
SQL Server关于apply的两种形式cross apply 和 outer apply
ASP.NET MVC 模型的自定义验证
nvm安装及常用命令
SQL Server 中数据类型转换
SQL Server 中WITH AS短语的使用
IE浏览器下AJAX缓存问题导致数据不更新的解决办法
订阅号