ArgumentOutOfRangeException 类

定义

当自变量的值超出了所调用方法定义的允许值范围时引发的异常。

public ref class ArgumentOutOfRangeException : ArgumentException
public class ArgumentOutOfRangeException : ArgumentException
[System.Serializable]
public class ArgumentOutOfRangeException : ArgumentException
[System.Serializable]
[System.Runtime.InteropServices.ComVisible(true)]
public class ArgumentOutOfRangeException : ArgumentException
type ArgumentOutOfRangeException = class
    inherit ArgumentException
type ArgumentOutOfRangeException = class
    inherit ArgumentException
    interface ISerializable
[<System.Serializable>]
type ArgumentOutOfRangeException = class
    inherit ArgumentException
    interface ISerializable
[<System.Serializable>]
[<System.Runtime.InteropServices.ComVisible(true)>]
type ArgumentOutOfRangeException = class
    inherit ArgumentException
    interface ISerializable
Public Class ArgumentOutOfRangeException
Inherits ArgumentException
继承
ArgumentOutOfRangeException
继承
ArgumentOutOfRangeException
属性
实现

示例

以下示例定义一个类,该类包含有关受邀来宾的信息。 如果来宾小于 21, ArgumentOutOfRangeException 则会引发异常。

using System;
using static System.Console;

public class Program
{
    public static void Main(string[] args)
    {
        try
        {
            var guest1 = new Guest("Ben", "Miller", 17);
            WriteLine(guest1.GuestInfo);
        }
        catch (ArgumentOutOfRangeException argumentOutOfRangeException)
        {
            WriteLine($"Error: {argumentOutOfRangeException.Message}");
        }
    }
}

class Guest
{
    private const int minimumRequiredAge = 21;

    private string firstName;
    private string lastName;
    private int age;

    public Guest(string firstName, string lastName, int age)
    {
        if (age < minimumRequiredAge)
            throw new ArgumentOutOfRangeException(nameof(age), $"All guests must be {minimumRequiredAge}-years-old or older.");

        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
    }

    public string GuestInfo => $"{firstName} {lastName}, {age}";
}
open System

type Guest(fName: string, lName: string, age: int) =
    let minimumRequiredAge = 21

    do if age < minimumRequiredAge then 
        raise (ArgumentOutOfRangeException(nameof age, $"All guests must be {minimumRequiredAge}-years-old or older."))

    member _.FirstName = fName
    member _.LastName = lName
    member _.GuestInfo() = $"{fName} {lName}, {age}"

try
    let guest1 = Guest("Ben", "Miller", 17);
    printfn $"{guest1.GuestInfo()}"
with
| :? ArgumentOutOfRangeException as e ->
    printfn $"Error: {e.Message}"
Module Module1
   Public Sub Main()
       Try
           Dim guest1 As Guest = New Guest("Ben", "Miller", 17)
           Console.WriteLine(guest1.GuestInfo)
       Catch outOfRange As ArgumentOutOfRangeException
           Console.WriteLine("Error: {0}", outOfRange.Message)
       End Try
   End Sub
End Module

Class Guest
    Private FirstName As String
    Private LastName As String
    Private Age As Integer

    Public Sub New(ByVal fName As String, ByVal lName As String, ByVal age As Integer)
        MyBase.New()
        FirstName = fName
        LastName = lName
        If (age < 21) Then
            Throw New ArgumentOutOfRangeException("age", "All guests must be 21-years-old or older.")
        Else
            age = age
        End If
    End Sub

    Public Function GuestInfo() As String
        Dim gInfo As String = (FirstName + (" " _
                    + (Me.LastName + (", " + Me.Age.ToString))))
        Return gInfo
    End Function
End Class

注解

ArgumentOutOfRangeException调用方法并且至少传递给该方法的一个参数不包含null并且包含无效值,该值不是参数预期值集的成员时引发异常。 该 ParamName 属性标识无效参数, ActualValue 如果存在值,则属性标识无效值。

通常, ArgumentOutOfRangeException 开发人员错误的结果。 不应在块中 try/catch 处理异常,而是应消除异常的原因,或者,如果在将参数传递给引发异常的方法之前由方法调用或输入返回,则应在将参数传递给该方法之前验证参数。

ArgumentOutOfRangeException 通过以下方法广泛使用:

引发异常的条件 ArgumentOutOfRangeException 包括:

  • 您正按其索引号检索集合的成员,索引号无效。

    这是异常的 ArgumentOutOfRangeException 最常见原因。 通常,索引号因以下四个原因之一无效:

    1. 该集合没有成员,并且代码假定它确实存在。 以下示例尝试检索没有元素的集合的第一个元素:

      using System;
      using System.Collections.Generic;
      
      public class Example4
      {
         public static void Main()
         {
            var list = new List<string>();
            Console.WriteLine("Number of items: {0}", list.Count);
            try {
               Console.WriteLine("The first item: '{0}'", list[0]);
            }
            catch (ArgumentOutOfRangeException e) {
               Console.WriteLine(e.Message);
            }
         }
      }
      // The example displays the following output:
      //   Number of items: 0
      //   Index was out of range. Must be non-negative and less than the size of the collection.
      //   Parameter name: index
      
      open System
      
      
      let list = ResizeArray<string>()
      printfn $"Number of items: {list.Count}"
      try
          printfn $"The first item: '{list[0]}'"
      with 
      | :? ArgumentOutOfRangeException as e ->
          printfn $"{e.Message}"
      
      // The example displays the following output:
      //   Number of items: 0
      //   Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'index')
      
      Imports System.Collections.Generic
      
      Module Example
         Public Sub Main()
            Dim list As New List(Of String)
            Console.WriteLine("Number of items: {0}", list.Count)
            Try
               Console.WriteLine("The first item: '{0}'", list(0))
            Catch e As ArgumentOutOfRangeException
               Console.WriteLine(e.Message)
            End Try
         End Sub
      End Module
      ' The example displays the following output:
      '   Number of items: 0
      '   Index was out of range. Must be non-negative and less than the size of the collection.
      '   Parameter name: index
      

      若要防止异常,请在尝试检索任何成员之前检查集合 Count 的属性是否大于零,如以下代码片段所示。

      if (list.Count > 0)
         Console.WriteLine("The first item: '{0}'", list[0]);
      
      if list.Count > 0 then
          printfn $"The first item: '{list[0]}'"
      
      If list.Count > 0 Then
         Console.WriteLine("The first item: '{0}'", list(0))
      End If
      
    2. 在某些情况下,可能会发生异常,因为您正尝试使用不存在的索引(而不是调用此方法)将成员添加到集合中,例如 Add出于此目的而存在的方法。 以下示例尝试使用不存在的索引(而不是调用 List<T>.Add 该方法)将元素添加到集合中。

      using System;
      using System.Collections.Generic;
      
      public class Example13
      {
         public static void Main()
         {
            var numbers = new List<int>();
            numbers.AddRange( new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 20 } );
      
            var squares = new List<int>();
            for (int ctr = 0; ctr < numbers.Count; ctr++)
               squares[ctr] = (int) Math.Pow(numbers[ctr], 2);
         }
      }
      // The example displays the following output:
      //    Unhandled Exception: System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
      //    Parameter name: index
      //       at System.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource)
      //       at Example.Main()
      
      let numbers = ResizeArray<int>()
      numbers.AddRange [ 0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 20 ]
      
      let squares = ResizeArray<int>()
      for  ctr = 0 to numbers.Count - 1 do
          squares[ctr] <- int (float numbers[ctr] ** 2)
      
      // The example displays the following output:
      //    Unhandled Exception: System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'index')
      //       at System.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource)
      //       at <StartupCode$argumentoutofrangeexception>.$NoElements.main@()
      
      Imports System.Collections.Generic
      
      Module Example
         Public Sub Main()
            Dim numbers As New List(Of Integer)
            numbers.AddRange( { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 20 } )
            
            Dim squares As New List(Of Integer)
            For ctr As Integer = 0 To numbers.Count - 1
               squares(ctr) = CInt(numbers(ctr) ^ 2) 
            Next
         End Sub
      End Module
      ' The example displays the following output:
      '    Unhandled Exception: System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
      '    Parameter name: index
      '       at System.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource)
      '       at Example.Main()
      

      以下代码片段更正了此错误:

      var squares = new List<int>();
      for (int ctr = 0; ctr < numbers.Count; ctr++)
         squares.Add((int) Math.Pow(numbers[ctr], 2));
      
      let squares = ResizeArray<int>()
      for ctr = 0 to numbers.Count - 1 do
          squares.Add(int (float numbers[ctr] ** 2))
      
      Dim squares As New List(Of Integer)
      For ctr As Integer = 0 To numbers.Count - 1
         squares.Add(CInt(numbers(ctr) ^ 2)) 
      Next
      
    3. 您正尝试检索其索引为负的项。 这通常是因为你已搜索某个特定元素的索引的集合,并且错误地假定搜索成功。 在下面的示例中,对方法的调用 List<T>.FindIndex(Predicate<T>) 找不到等于“Z”的字符串,因此返回 -1。 但是,这是无效的索引值。

      using System;
      using System.Collections.Generic;
      
      public class Example
      {
         public static void Main()
         {
            var list = new List<string>();
            list.AddRange( new String[] { "A", "B", "C" } );
            // Get the index of the element whose value is "Z".
            int index = list.FindIndex((new StringSearcher("Z")).FindEquals);
            try {
               Console.WriteLine("Index {0} contains '{1}'", index, list[index]);
            }
            catch (ArgumentOutOfRangeException e) {
               Console.WriteLine(e.Message);
            }
         }
      }
      
      internal class StringSearcher
      {
         string value;
      
         public StringSearcher(string value)
         {
            this.value = value;
         }
      
         public bool FindEquals(string s)
         {
            return s.Equals(value, StringComparison.InvariantCulture);
         }
      }
      // The example displays the following output:
      //   Index was out of range. Must be non-negative and less than the size of the collection.
      //   Parameter name: index
      
      open System
      
      module StringSearcher =
          let findEquals (s: string) value =
              s.Equals(value, StringComparison.InvariantCulture)
      
      let list = ResizeArray<string>()
      list.AddRange [ "A"; "B"; "C" ]
      // Get the index of the element whose value is "Z".
      let index = list.FindIndex(StringSearcher.findEquals "Z")
      try 
          printfn $"Index {index} contains '{list[index]}'"
      with 
      | :? ArgumentOutOfRangeException as e ->
          printfn $"{e.Message}" 
      
      // The example displays the following output:
      //   Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'index')
      
      Imports System.Collections.Generic
      
      Module Example
         Public Sub Main()
            Dim list As New List(Of String) 
            list.AddRange( { "A", "B", "C" } )
            ' Get the index of the element whose value is "Z".
            Dim index As Integer = list.FindIndex(AddressOf (New StringSearcher("Z")).FindEquals)
            Try
               Console.WriteLine("Index {0} contains '{1}'", index, list(index)) 
            Catch e As ArgumentOutOfRangeException
               Console.WriteLine(e.Message)
            End Try
         End Sub
      End Module
      
      Friend Class StringSearcher
         Dim value As String
         
         Public Sub New(value As String)
            Me.value = value
         End Sub
         
         Public Function FindEquals(s As String) As Boolean
            Return s.Equals(value, StringComparison.InvariantCulture) 
         End Function
      End Class
      ' The example displays the following output:
      '   Index was out of range. Must be non-negative and less than the size of the collection.
      '   Parameter name: index
      

      若要防止异常,请检查搜索是否成功,确保返回的索引大于或等于零,然后再尝试从集合中检索项,如以下代码片段所示。

      // Get the index of the element whose value is "Z".
      int index = list.FindIndex((new StringSearcher("Z")).FindEquals);
      if (index >= 0)
         Console.WriteLine("'Z' is found at index {0}", list[index]);
      
      // Get the index of the element whose value is "Z".
      let index = list.FindIndex(StringSearcher.findEquals "Z")
      if index >= 0 then
          printfn $"'Z' is found at index {list[index]}"
      
      ' Get the index of the element whose value is "Z".
      Dim index As Integer = list.FindIndex(AddressOf (New StringSearcher("Z")).FindEquals)
      If index >= 0 Then
         Console.WriteLine("Index {0} contains '{1}'", index, list(index)) 
      End If
      
    4. 尝试检索索引等于集合 Count 属性的值的元素,如以下示例所示。

      using System;
      using System.Collections.Generic;
      
      public class Example8
      {
         public static void Main()
         {
            var list = new List<string>();
            list.AddRange( new String[] { "A", "B", "C" } );
            try {
               // Display the elements in the list by index.
               for (int ctr = 0; ctr <= list.Count; ctr++)
                  Console.WriteLine("Index {0}: {1}", ctr, list[ctr]);
            }
            catch (ArgumentOutOfRangeException e) {
               Console.WriteLine(e.Message);
            }
         }
      }
      // The example displays the following output:
      //   Index 0: A
      //   Index 1: B
      //   Index 2: C
      //   Index was out of range. Must be non-negative and less than the size of the collection.
      //   Parameter name: index
      
      open System
      
      let list = ResizeArray<string>()
      list.AddRange [ "A"; "B"; "C" ] 
      try
          // Display the elements in the list by index.
          for i = 0 to list.Count do
              printfn $"Index {i}: {list[i]}"
      with 
      | :? ArgumentOutOfRangeException as e ->
          printfn $"{e.Message}" 
            
      // The example displays the following output:
      //   Index 0: A
      //   Index 1: B
      //   Index 2: C
      //   Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'index')
      
      Imports System.Collections.Generic
      
      Module Example
         Public Sub Main()
            Dim list As New List(Of String) 
            list.AddRange( { "A", "B", "C" } )
            Try
               ' Display the elements in the list by index.
               For ctr As Integer = 0 To list.Count
                  Console.WriteLine("Index {0}: {1}", ctr, list(ctr)) 
               Next   
            Catch e As ArgumentOutOfRangeException
               Console.WriteLine(e.Message)
            End Try
         End Sub
      End Module
      ' The example displays the following output:
      '   Index 0: A
      '   Index 1: B
      '   Index 2: C
      '   Index was out of range. Must be non-negative and less than the size of the collection.
      '   Parameter name: index
      

      由于 .NET 中的集合使用从零开始的索引,因此集合的第一个元素为索引 0,最后一个元素位于索引 Count - 1。 可以通过确保访问索引 Count 处的最后一个元素 - 1(如以下代码所示)来消除错误。

      // Display the elements in the list by index.
      for (int ctr = 0; ctr < list.Count; ctr++)
         Console.WriteLine("Index {0}: {1}", ctr, list[ctr]);
      
      // Display the elements in the list by index.
      for i = 0 to list.Count - 1 do
          printfn $"Index {i}: {list[i]}"
      
      ' Display the elements in the list by index.
      For ctr As Integer = 0 To list.Count - 1 
         Console.WriteLine("Index {0}: {1}", ctr, list(ctr)) 
      Next
      
  • 尝试通过调用字符串操作方法执行字符串操作,并且字符串中不存在起始索引。

    方法(如String.CompareString.CompareOrdinal、、String.IndexOfIndexOfAnyString.InsertString.LastIndexOf、、String.LastIndexOfAnyRemoveString.Substring的重载,或者允许指定操作的起始索引要求索引是字符串中的有效位置。 有效索引范围为 0 到 String.Length 1。

    ArgumentOutOfRangeException 异常有四个常见原因:

    1. 你正在使用空字符串,或者 String.Empty。 由于其 String.Length 属性返回 0,因此任何通过索引操作它的尝试都引发异常 ArgumentOutOfRangeException 。 以下示例定义返回字符串的第一 GetFirstCharacter 个字符的方法。 如果字符串为空,因为传递给该方法的最后一个字符串,该方法将引发异常 ArgumentOutOfRangeException

      using System;
      
      public class Example1
      {
          public static void Main()
          {
              String[] words = { "the", "today", "tomorrow", " ", "" };
              foreach (var word in words)
                  Console.WriteLine("First character of '{0}': '{1}'",
                                    word, GetFirstCharacter(word));
          }
      
          private static char GetFirstCharacter(string s)
          {
              return s[0];
          }
      }
      // The example displays the following output:
      //    First character of //the//: //t//
      //    First character of //today//: //t//
      //    First character of //tomorrow//: //t//
      //    First character of // //: // //
      //
      //    Unhandled Exception: System.IndexOutOfRangeException: Index was outside the bounds of the array.
      //       at Example.Main()
      
      open System
      
      let getFirstCharacter (s: string) = s[0]
      
      let words = [ "the"; "today"; "tomorrow"; " "; "" ]
      for word in words do
          printfn $"First character of '{word}': '{getFirstCharacter word}'"
      
      // The example displays the following output:
      //    First character of 'the': 't'
      //    First character of 'today': 't'
      //    First character of 'tomorrow': 't'
      //    First character of ' ': ' '
      //
      //    Unhandled Exception: System.IndexOutOfRangeException: Index was outside the bounds of the array.
      //       at <StartupCode$argumentoutofrangeexception>.$EmptyString1.main@()
      
      Module Example
         Public Sub Main()
             Dim words() As String = { "the", "today", "tomorrow", " ", "" }
             For Each word In words
                Console.WriteLine("First character of '{0}': '{1}'", 
                                  word, GetFirstCharacter(word))
             Next                     
         End Sub
         
         Private Function GetFirstCharacter(s As String) As Char
            Return s(0)
         End Function
      End Module
      ' The example displays the following output:
      '    First character of 'the': 't'
      '    First character of 'today': 't'
      '    First character of 'tomorrow': 't'
      '    First character of ' ': ' '
      '    
      '    Unhandled Exception: System.IndexOutOfRangeException: Index was outside the bounds of the array.
      '       at Example.Main()
      

      可以通过测试字符串 String.Length 是否大于零或调用 IsNullOrEmpty 方法来确保字符串不为 null 空来消除异常。 以下代码片段执行后者。 在这种情况下,如果字符串为 null 空,则 GetFirstCharacter 该方法返回 U+0000。

      static char GetFirstCharacter(string s)
      {
          if (string.IsNullOrEmpty(s))
              return '\u0000';
          else
              return s[0];
      }
      
      let getFirstCharacter (s: string) =
         if String.IsNullOrEmpty s then
            '\u0000'
         else
            s[0]
      
      Function GetFirstCharacter(s As String) As Char
         If String.IsNullOrEmpty(s) Then 
            Return ChrW(0)
         Else   
            Return s(0)
         End If   
      End Function
      
    2. 你正在根据该字符串中的子字符串的位置操作字符串,并且无法确定子字符串是否实际找到。

      以下示例提取两个单词短语的第二个单词。 如果短语仅包含一个 ArgumentOutOfRangeException 单词,因此不包含嵌入的空间字符,则引发异常。 之所以发生这种情况,是因为对方法的调用 String.IndexOf(String) 返回 -1 以指示搜索失败,然后此无效值将 String.Substring(Int32) 传递给该方法。

      using System;
      
      public class Example17
      {
         public static void Main()
         {
            String[] phrases = { "ocean blue", "concerned citizen",
                                 "runOnPhrase" };
            foreach (var phrase in phrases)
               Console.WriteLine("Second word is {0}", GetSecondWord(phrase));
         }
      
         static string GetSecondWord(string s)
         {
            int pos = s.IndexOf(" ");
            return s.Substring(pos).Trim();
         }
      }
      // The example displays the following output:
      //    Second word is blue
      //    Second word is citizen
      //
      //    Unhandled Exception: System.ArgumentOutOfRangeException: StartIndex cannot be less than zero.
      //    Parameter name: startIndex
      //       at System.String.Substring(Int32 startIndex, Int32 length)
      //       at Example17.GetSecondWord(String s)
      //       at Example17.Main()
      
      let getSecondWord (s: string) =
          let pos = s.IndexOf " "
          s.Substring(pos).Trim()
      
      let phrases = [ "ocean blue"; "concerned citizen"; "runOnPhrase" ]
      for phrase in phrases do
          printfn $"Second word is {getSecondWord phrase}"
      
      // The example displays the following output:
      //    Second word is blue
      //    Second word is citizen
      //
      //    Unhandled Exception: System.ArgumentOutOfRangeException: StartIndex cannot be less than zero. (Parameter 'startIndex')
      //       at System.String.Substring(Int32 startIndex, Int32 length)
      //       at System.String.Substring(Int32 startIndex)
      //       at NoFind1.getSecondWord(String s)
      //       at <StartupCode$argumentoutofrangeexception>.$NoFind1.main@()
      
      Module Example
         Public Sub Main()
            Dim phrases() As String = { "ocean blue", "concerned citizen", 
                                        "runOnPhrase" }
            For Each phrase In phrases
               Console.WriteLine("Second word is {0}", GetSecondWord(phrase))
            Next                            
        End Sub
        
        Function GetSecondWord(s As String) As String
           Dim pos As Integer = s.IndexOf(" ")
           Return s.Substring(pos).Trim()
        End Function
      End Module
      ' The example displays the following output:
      '       Second word is blue
      '       Second word is citizen
      '       
      '       Unhandled Exception: System.ArgumentOutOfRangeException: StartIndex cannot be less than zero.
      '       Parameter name: startIndex
      '          at System.String.Substring(Int32 startIndex, Int32 length)
      '          at Example.GetSecondWord(String s)
      '          at Example.Main()
      

      若要消除异常,请在调用字符串操作方法之前验证字符串搜索方法返回的值。

      using System;
      
      public class Example18
      {
         public static void Main()
         {
            String[] phrases = { "ocean blue", "concerned citizen",
                                 "runOnPhrase" };
            foreach (var phrase in phrases) {
               string word = GetSecondWord(phrase);
               if (! string.IsNullOrEmpty(word))
                  Console.WriteLine("Second word is {0}", word);
            }
         }
      
         static string GetSecondWord(string s)
         {
            int pos = s.IndexOf(" ");
            if (pos >= 0)
               return s.Substring(pos).Trim();
            else
               return string.Empty;
         }
      }
      // The example displays the following output:
      //       Second word is blue
      //       Second word is citizen
      
      open System
      
      let getSecondWord (s: string) =
          let pos = s.IndexOf " "
          if pos >= 0 then
              s.Substring(pos).Trim()
          else 
              String.Empty
      
      let phrases = [ "ocean blue"; "concerned citizen"; "runOnPhrase" ]
      for phrase in phrases do
          let word = getSecondWord phrase
          if not (String.IsNullOrEmpty word) then
              printfn $"Second word is {word}"
      
      // The example displays the following output:
      //       Second word is blue
      //       Second word is citizen
      
      Module Example
         Public Sub Main()
            Dim phrases() As String = { "ocean blue", "concerned citizen", 
                                        "runOnPhrase" }
            For Each phrase In phrases
               Dim word As String = GetSecondWord(phrase)
               If Not String.IsNullOrEmpty(word) Then _
                  Console.WriteLine("Second word is {0}", word)
            Next                            
         End Sub
        
         Function GetSecondWord(s As String) As String
            Dim pos As Integer = s.IndexOf(" ")
            If pos >= 0
                Return s.Substring(pos).Trim()
            Else
               Return String.Empty
            End If
        End Function
      End Module
      ' The example displays the following output:
      '       Second word is blue
      '       Second word is citizen
      
    3. 你已尝试提取当前字符串范围之外的子字符串。

      提取子字符串的方法都要求指定子字符串的起始位置,对于不继续到字符串末尾的子字符串,则子字符串中的字符数。 请注意,这不是子字符串中最后一个字符的 索引

      ArgumentOutOfRangeException在这种情况下,通常会引发异常,因为你错误地计算了子字符串中的字符数。 如果使用搜索方法,例如 String.IndexOf 标识子字符串的起始和结束位置:

      • 如果返回的 String.IndexOf 结束位置中的字符将包含在子字符串中,则子字符串的结束位置由公式提供

        endIndex - startIndex + 1
        
      • 如果要从子字符串中排除返回的 String.IndexOf 结束位置中的字符,则公式会给出子字符串的结束位置

        endIndex - startIndex
        

        以下示例定义一个 FindWords 方法,该方法使用 String.IndexOfAny(Char[], Int32) 该方法标识字符串中的空格字符和标点符号,并返回包含字符串中找到的单词的数组。

        using System;
        using System.Collections.Generic;
        
        public class Example19
        {
           public static void Main()
           {
              string sentence = "This is a simple, short sentence.";
              Console.WriteLine("Words in '{0}':", sentence);
              foreach (var word in FindWords(sentence))
                 Console.WriteLine("   '{0}'", word);
           }
        
           static String[] FindWords(string s)
           {
              int start = 0, end = 0;
              Char[] delimiters = { ' ', '.', ',', ';', ':', '(', ')' };
              var words = new List<string>();
        
              while (end >= 0) {
                 end = s.IndexOfAny(delimiters, start);
                 if (end >= 0) {
                    if (end - start > 0)
                       words.Add(s.Substring(start, end - start));
        
                    start = end + 1;
                 }
                 else {
                    if (start < s.Length - 1)
                       words.Add(s.Substring(start));
                 }
              }
              return words.ToArray();
           }
        }
        // The example displays the following output:
        //       Words in 'This is a simple, short sentence.':
        //          'This'
        //          'is'
        //          'a'
        //          'simple'
        //          'short'
        //          'sentence'
        
        
        let findWords (s: string) =
            let mutable start, end' = 0, 0
            let delimiters = [| ' '; '.'; ','; ';'; ':'; '('; ')' |]
            let words = ResizeArray<string>()
            while end' >= 0 do
                end' <- s.IndexOfAny(delimiters, start)
                if end' >= 0 then
                    if end' - start > 0 then
                        words.Add(s.Substring(start, end' - start))
                    start <- end' + 1
                elif start < s.Length - 1 then
                    words.Add(s.Substring start)
            words.ToArray()
        
        let sentence = "This is a simple, short sentence."
        printfn $"Words in '{sentence}':"
        for word in findWords sentence do
            printfn $"   '{word}'"
        
        // The example displays the following output:
        //       Words in 'This is a simple, short sentence.':
        //          'This'
        //          'is'
        //          'a'
        //          'simple'
        //          'short'
        //          'sentence'
        
        Imports System.Collections.Generic
        
        Module Example
           Public Sub Main()
              Dim sentence As String = "This is a simple, short sentence."
              Console.WriteLine("Words in '{0}':", sentence)
              For Each word In FindWords(sentence)
                 Console.WriteLine("   '{0}'", word)
              Next
           End Sub
           
           Function FindWords(s As String) As String()
              Dim start, ending As Integer
              Dim delimiters() As Char = { " "c, "."c, ","c, ";"c, ":"c,
                                           "("c, ")"c }
              Dim words As New List(Of String)()
        
              Do While ending >= 0
                 ending = s.IndexOfAny(delimiters, start)
                 If ending >= 0
                    If ending - start > 0 Then
                       words.Add(s.Substring(start, ending - start)) 
                    End If
                    start = ending + 1
                 Else
                    If start < s.Length - 1 Then
                       words.Add(s.Substring(start))
                    End If      
                 End If
              Loop    
              Return words.ToArray()                         
           End Function
        End Module
        ' The example displays the following output:
        '       Words in 'This is a simple, short sentence.':
        '          'This'
        '          'is'
        '          'a'
        '          'simple'
        '          'short'
        '          'sentence'
        
  • 已将负数传递给一个仅需要正数和零的参数的方法,或者已将负数或零传递给具有仅需要正数的参数的方法。

    例如,该方法 Array.CreateInstance(Type, Int32, Int32, Int32) 要求指定二维数组的每个维度中的元素数;每个维度的有效值可以介于 0 到 Int32.MaxValue0 之间。 但是,由于以下示例中的维度参数具有负值,因此该方法将引发异常 ArgumentOutOfRangeException

    using System;
    
    public class Example01
    {
        public static void Main()
        {
            int dimension1 = 10;
            int dimension2 = -1;
            try
            {
                Array arr = Array.CreateInstance(typeof(string),
                                                 dimension1, dimension2);
            }
            catch (ArgumentOutOfRangeException e)
            {
                if (e.ActualValue != null)
                    Console.WriteLine("{0} is an invalid value for {1}: ", e.ActualValue, e.ParamName);
                Console.WriteLine(e.Message);
            }
        }
    }
    // The example displays the following output:
    //     Non-negative number required.
    //     Parameter name: length2
    
    open System
    
    let dimension1 = 10
    let dimension2 = -1
    try
        let arr = Array.CreateInstance(typeof<string>, dimension1, dimension2)
        printfn "%A" arr
    with 
    | :? ArgumentOutOfRangeException as e ->
        if not (isNull e.ActualValue) then
            printfn $"{e.ActualValue} is an invalid value for {e.ParamName}: "
        printfn $"{e.Message}"
    
    // The example displays the following output:
    //     Non-negative number required. (Parameter 'length2')
    
    Module Example
       Public Sub Main()
          Dim dimension1 As Integer = 10
          Dim dimension2 As Integer = -1
          Try
             Dim arr AS Array = Array.CreateInstance(GetType(String), 
                                                     dimension1, dimension2)
          Catch e As ArgumentOutOfRangeException
             If e.ActualValue IsNot Nothing Then
                Console.WriteLine("{0} is an invalid value for {1}: ", 
                                  e.ActualValue, e.ParamName)
             End If                     
             Console.WriteLine(e.Message)
          End Try
       End Sub
    End Module
    ' The example displays the following output:
    '     Non-negative number required.
    '     Parameter name: length2
    

    若要更正错误,请确保无效参数的值为非负值。 可以通过提供有效值来执行此操作,如以下代码片段所示。

    int dimension1 = 10;
    int dimension2 = 10;
    Array arr = Array.CreateInstance(typeof(string),
                                     dimension1, dimension2);
    
    let dimension1 = 10
    let dimension2 = 10
    let arr = Array.CreateInstance(typeof<string>, dimension1, dimension2)
    printfn "%A" arr
    
    Dim dimension1 As Integer = 10
    Dim dimension2 As Integer = 10
    Dim arr As Array = Array.CreateInstance(GetType(String), 
                                            dimension1, dimension2)
    

    还可以验证输入,如果输入无效,请执行一些操作。 以下代码片段显示错误消息,而不是调用该方法。

    if (dimension1 < 0 || dimension2 < 0)
    {
        Console.WriteLine("Unable to create the array.");
        Console.WriteLine("Specify non-negative values for the two dimensions.");
    }
    else
    {
        arr = Array.CreateInstance(typeof(string),
                                   dimension1, dimension2);
    }
    
    if dimension1 < 0 || dimension2 < 0 then
        printfn "Unable to create the array."
        printfn "Specify non-negative values for the two dimensions."
    else
        let arr = Array.CreateInstance(typeof<string>, dimension1, dimension2)
        printfn "%A" arr
    
    If dimension1 < 0 OrElse dimension2 < 0 Then
       Console.WriteLine("Unable to create the array.")
       Console.WriteLine("Specify non-negative values for the two dimensions.")
    Else
       arr = Array.CreateInstance(GetType(String), 
                                  dimension1, dimension2)   
    End If
    
  • 争用条件存在于多线程应用或具有异步执行的任务以及更新数组或集合的任务中。

    以下示例使用对象 List<T> 填充对象的集合 Continent 。 如果示例尝试在完全填充集合之前显示集合中的七个项,则会引发 ArgumentOutOfRangeException 该事件。

    using System;
    using System.Collections.Generic;
    using System.Threading;
    
    public class Continent
    {
       public string Name { get; set; }
       public int Population { get; set; }
       public Decimal Area { get; set; }
    }
    
    public class Example11
    {
       static List<Continent> continents = new List<Continent>();
       static string msg;
    
       public static void Main()
       {
          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(msg);
          Console.WriteLine();
    
          // Display the list.
          for (int ctr = 0; ctr < names.Length; ctr++) {
             var continent = continents[ctr];
             Console.WriteLine("{0}: Area: {1}, Population {2}",
                               continent.Name, continent.Population,
                               continent.Area);
          }
       }
    
       private static void PopulateContinents(Object obj)
       {
          string name = obj.ToString();
          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);
       }
    }
    // The example displays output like the following:
    //    Adding //Africa// to the list.
    //    Adding //Antarctica// to the list.
    //    Adding //Asia// to the list.
    //    Adding //Australia// to the list.
    //    Adding //Europe// to the list.
    //    Adding //North America// to the list.
    //    Adding //South America// to the list.
    //
    //
    //
    //    Unhandled Exception: System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
    //    Parameter name: index
    //       at System.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource)
    //       at Example.Main()
    
    open System.Threading
    
    type Continent =
        { Name: string
          Population: int
          Area: decimal }
    
    let continents = ResizeArray<Continent>()
    let mutable msg = ""
    
    let names = 
        [ "Africa"; "Antarctica"; "Asia"
          "Australia"; "Europe"; "North America"
          "South America" ]
    
    let populateContinents obj = 
        let name = string obj
        msg <- msg + $"Adding '{name}' to the list.\n"
        // Sleep to simulate retrieving data.
        Thread.Sleep 50
        let continent = 
            { Name = name
              Population = 0
              Area = 0M }
        continents.Add continent
          
    // Populate the list.
    for name in names do
        let th = Thread(ParameterizedThreadStart populateContinents)
        th.Start name
          
    printfn $"{msg}\n"
    
    // Display the list.
    for i = 0 to names.Length - 1 do
        let continent = continents[i]
        printfn $"{continent.Name}: Area: {continent.Population}, Population {continent.Area}"
    
    // The example displays output like the following:
    //    Unhandled Exception: System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'index')
    //       at System.Collections.Generic.List`1.get_Item(Int32 index)
    //       at <StartupCode$argumentoutofrangeexception>.$Race1.main@()
    
    Imports System.Collections.Generic
    Imports System.Threading
    
    Public Class Continent
       Public Property Name As String
       Public Property Population As Integer
       Public Property Area As Decimal  
    End Class
    
    Module Example
       Dim continents As New List(Of Continent)
       Dim msg As String 
          
       Public Sub Main()
          Dim names() As String = { "Africa", "Antarctica", "Asia", 
                                         "Australia", "Europe", "North America",
                                         "South America" }
          ' Populate the list.
          For Each name In names
             Dim th As New Thread(AddressOf PopulateContinents)
             th.Start(name)
          Next              
          Console.WriteLine(msg)
          Console.WriteLine()
    
          ' Display the list.
          For ctr As Integer = 0 To names.Length - 1
             Dim continent = continents(ctr)
             Console.WriteLine("{0}: Area: {1}, Population {2}", 
                               continent.Name, continent.Population,
                               continent.Area)
          Next
       End Sub
       
       Private Sub PopulateContinents(obj As Object)
          Dim name As String = obj.ToString()
          msg += String.Format("Adding '{0}' to the list.{1}", name, vbCrLf)
          Dim continent As New Continent()
          continent.Name = name
          ' Sleep to simulate retrieving remaining data.
          Thread.Sleep(50)
          continents.Add(continent)
       End Sub
    End Module
    ' The example displays output like the following:
    '    Adding 'Africa' to the list.
    '    Adding 'Antarctica' to the list.
    '    Adding 'Asia' to the list.
    '    Adding 'Australia' to the list.
    '    Adding 'Europe' to the list.
    '    Adding 'North America' to the list.
    '    Adding 'South America' to the list.
    '    
    '    
    '    
    '    Unhandled Exception: System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
    '    Parameter name: index
    '       at System.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource)
    '       at Example.Main()
    

    在这种情况下,可从多个线程访问两个资源:

    • continents 集合。 从多个线程调用其 List<T>.Add 方法。 此外,主线程或主线程假定在循环访问其成员时,集合已完全填充 7 个元素。

    • msg 多个线程串联的字符串。

    若要更正此错误,请确保以线程安全的方式访问共享状态,如下所示。

    • 如果应用使用数组或集合对象,请考虑使用线程安全集合类,例如命名空间中的类型 System.Collections.ConcurrentSystem.Collections.Immutable 带外版本。

    • 确保共享状态 (即多个线程可以访问的资源) 以线程安全的方式访问,因此一次只有一个线程具有对资源的独占访问权限。 大量类(如 CountdownEventInterlockedMonitorMutex)可用于同步对资源的访问。 有关详细信息,请参阅 线程处理。 此外,语言支持通过 C# 中的 lock 语句和 Visual Basic 中的 SyncLock 构造提供。

    以下示例解决了 ArgumentOutOfRangeException 上一示例中的其他问题。 它将对象替换为 List<T> 一个 ConcurrentBag<T> 对象,以确保对集合的访问是线程安全的,使用 CountdownEvent 对象来确保应用程序线程仅在执行其他线程后继续,并使用锁来确保一次只能有一个线程访问 msg 变量。

    using System;
    using System.Collections.Concurrent;
    using System.Threading;
    
    public class ContinentD
    {
       public string Name { get; set; }
       public int Population { get; set; }
       public Decimal Area { get; set; }
    }
    
    public class Example12
    {
       static ConcurrentBag<ContinentD> ContinentDs = new ConcurrentBag<ContinentD>();
       static CountdownEvent gate;
       static string msg = string.Empty;
    
       public static void Main()
       {
          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();
       }
    }
    // The example displays output like the following:
    //       Adding 'Africa' to the list.
    //       Adding 'Antarctica' to the list.
    //       Adding 'Asia' to the list.
    //       Adding 'Australia' to the list.
    //       Adding 'Europe' to the list.
    //       Adding 'North America' to the list.
    //       Adding 'South America' to the list.
    //
    //
    //       Africa: Area: 0, Population 0
    //       Antarctica: Area: 0, Population 0
    //       Asia: Area: 0, Population 0
    //       Australia: Area: 0, Population 0
    //       Europe: Area: 0, Population 0
    //       North America: Area: 0, Population 0
    //       South America: Area: 0, Population 0
    
    open System.Collections.Concurrent
    open System.Threading
    
    type Continent =
        { Name: string
          Population: int
          Area: decimal }
    
    let continents = ConcurrentBag<Continent>();
    let mutable msg = ""
    
    let names = 
        [ "Africa"; "Antarctica"; "Asia"
          "Australia"; "Europe"; "North America"
          "South America" ]
    
    let gate = new CountdownEvent(names.Length)
    
    let populateContinents obj = 
        let name = string obj
        lock msg (fun () -> 
            msg <- msg + $"Adding '{name}' to the list.\n" )
    
        // Sleep to simulate retrieving remaining data.
        let continent = 
            { Name = name
              Population = 0
              Area = 0M }
        Thread.Sleep 25
        continents.Add continent
        gate.Signal() |> ignore
    
    // Populate the list.
    for name in names do
        let th = Thread(ParameterizedThreadStart populateContinents)
        th.Start name
    
    // Display the list.
    gate.Wait();
    printfn $"{msg}\n"
    
    let arr = continents.ToArray();
    for i = 0 to names.Length - 1 do
        let continent = arr[i]
        printfn $"{continent.Name}: Area: {continent.Population}, Population {continent.Area}"
    
    // The example displays output like the following:
    //       Adding 'Africa' to the list.
    //       Adding 'Antarctica' to the list.
    //       Adding 'Asia' to the list.
    //       Adding 'Australia' to the list.
    //       Adding 'Europe' to the list.
    //       Adding 'North America' to the list.
    //       Adding 'South America' to the list.
    //
    //
    //       Africa: Area: 0, Population 0
    //       Antarctica: Area: 0, Population 0
    //       Asia: Area: 0, Population 0
    //       Australia: Area: 0, Population 0
    //       Europe: Area: 0, Population 0
    //       North America: Area: 0, Population 0
    //       South America: Area: 0, Population 0
    
    Imports System.Collections.Concurrent
    Imports System.Threading
    
    Public Class Continent
       Public Property Name As String
       Public Property Population As Integer
       Public Property Area As Decimal  
    End Class
    
    Module Example
       Dim continents As New ConcurrentBag(Of Continent)
       Dim gate As CountdownEvent
       Dim msg As String = String.Empty
          
       Public Sub Main()
          Dim names() As String = { "Africa", "Antarctica", "Asia", 
                                    "Australia", "Europe", "North America",
                                    "South America" }
          gate = new CountdownEvent(names.Length)
          
          ' Populate the list.
          For Each name In names
             Dim th As New Thread(AddressOf PopulateContinents)
             th.Start(name)
          Next              
    
          ' Display the list.
          gate.Wait()
          Console.WriteLine(msg)
          Console.WriteLine()
    
          For ctr As Integer = 0 To names.Length - 1
             Dim continent = continents(ctr)
             Console.WriteLine("{0}: Area: {1}, Population {2}", 
                               continent.Name, continent.Population,
                               continent.Area)
          Next
       End Sub
       
       Private Sub PopulateContinents(obj As Object)
          Dim name As String = obj.ToString()
          SyncLock msg 
             msg += String.Format("Adding '{0}' to the list.{1}", name, vbCrLf)
          End SyncLock
          Dim continent As New Continent()
          continent.Name = name
          ' Sleep to simulate retrieving remaining data.
          Thread.Sleep(25)
          continents.Add(continent)
          gate.Signal()
       End Sub
    End Module
    ' The example displays output like the following:
    '    Adding 'Africa' to the list.
    '    Adding 'Antarctica' to the list.
    '    Adding 'Asia' to the list.
    '    Adding 'Australia' to the list.
    '    Adding 'Europe' to the list.
    '    Adding 'North America' to the list.
    '    Adding 'South America' to the list.
    '    
    '    
    '    Africa: Area: 0, Population 0
    '    Antarctica: Area: 0, Population 0
    '    Asia: Area: 0, Population 0
    '    Australia: Area: 0, Population 0
    '    Europe: Area: 0, Population 0
    '    North America: Area: 0, Population 0
    '    South America: Area: 0, Population 0
    

ArgumentOutOfRangeException 使用具有值0x80131502的 HRESULT COR_E_ARGUMENTOUTOFRANGE。

有关实例的初始属性值的列表ArgumentOutOfRangeException,请参阅ArgumentOutOfRangeException构造函数。

构造函数

ArgumentOutOfRangeException()

初始化 ArgumentOutOfRangeException 类的新实例。

ArgumentOutOfRangeException(SerializationInfo, StreamingContext)

用序列化数据初始化 ArgumentOutOfRangeException 类的新实例。

ArgumentOutOfRangeException(String)

使用导致此异常的参数的名称初始化 ArgumentOutOfRangeException 类的新实例。

ArgumentOutOfRangeException(String, Exception)

使用指定的错误消息和引发此异常的异常初始化 ArgumentOutOfRangeException 类的新实例。

ArgumentOutOfRangeException(String, Object, String)

使用指定的错误消息、参数名和参数值来初始化 ArgumentOutOfRangeException 类的新实例。

ArgumentOutOfRangeException(String, String)

使用指定的错误消息和导致此异常的参数的名称来初始化 ArgumentOutOfRangeException 类的新实例。

属性

ActualValue

获取导致此异常的参数值。

Data

获取键/值对的集合,这些键/值对提供有关该异常的其他用户定义信息。

(继承自 Exception)
HelpLink

获取或设置指向与此异常关联的帮助文件链接。

(继承自 Exception)
HResult

获取或设置 HRESULT(一个分配给特定异常的编码数字值)。

(继承自 Exception)
InnerException

获取导致当前异常的 Exception 实例。

(继承自 Exception)
Message

获取错误消息和无效参数值的字符串表示形式;或者,如果该参数值为 null,则仅获取错误消息。

ParamName

获取导致该异常的参数的名称。

(继承自 ArgumentException)
Source

获取或设置导致错误的应用程序或对象的名称。

(继承自 Exception)
StackTrace

获取调用堆栈上的即时框架字符串表示形式。

(继承自 Exception)
TargetSite

获取引发当前异常的方法。

(继承自 Exception)

方法

Equals(Object)

确定指定对象是否等于当前对象。

(继承自 Object)
GetBaseException()

当在派生类中重写时,返回 Exception,它是一个或多个并发的异常的根本原因。

(继承自 Exception)
GetHashCode()

作为默认哈希函数。

(继承自 Object)
GetObjectData(SerializationInfo, StreamingContext)

设置带有无效参数值和附加异常信息的 SerializationInfo 对象。

GetObjectData(SerializationInfo, StreamingContext)

设置带有参数名和附加异常信息的 SerializationInfo 对象。

(继承自 ArgumentException)
GetType()

获取当前实例的运行时类型。

(继承自 Exception)
MemberwiseClone()

创建当前 Object 的浅表副本。

(继承自 Object)
ToString()

创建并返回当前异常的字符串表示形式。

(继承自 Exception)

事件

SerializeObjectState
已过时。

当异常被序列化用来创建包含有关该异常的徐列出数据的异常状态对象时会出现该问题。

(继承自 Exception)

适用于

另请参阅