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
- Наследование
- Наследование
- Атрибуты
- Реализации
Примеры
В следующем примере определяется класс, содержащий сведения о приглашенном госте. Если гость моложе 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 широко используется следующими средствами:
Классы в System.Collections пространствах имен и System.IO пространствах имен.
Класс Array.
Методы обработки строк в String классе.
К условиям, в которых ArgumentOutOfRangeException создается исключение, относятся следующие:
Вы извлеките элемент коллекции по его номеру индекса, а номер индекса недопустим.
Это наиболее распространенная причина ArgumentOutOfRangeException исключения. Как правило, номер индекса недопустим по одной из четырех причин:
Коллекция не имеет элементов, и код предполагает, что он делает. В следующем примере предпринимается попытка получить первый элемент коллекции без элементов:
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
В некоторых случаях может возникнуть исключение, так как вы пытаетесь добавить член в коллекцию с помощью индекса, который не существует, а не путем вызова метода, например
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
Вы пытаетесь получить элемент, индекс которого является отрицательным. Обычно это происходит потому, что вы искали коллекцию для индекса определенного элемента и ошибочно предположили, что поиск выполнен успешно. В следующем примере вызов 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
Вы пытаетесь получить элемент, индекс которого равен значению свойства коллекции
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.Compare, , String.CompareOrdinal, String.IndexOf, IndexOfAnyString.Substring String.InsertString.LastIndexOfString.LastIndexOfAnyRemove, или позволяют указать начальный индекс операции, чтобы индекс был допустимым положением в строке. Допустимые индексы варьируются от 0 до String.Length 1.
Существует четыре распространенных причины этого ArgumentOutOfRangeException исключения:
Вы работаете с пустой строкой или 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
Вы управляете строкой на основе позиции подстроки в этой строке, и вы не смогли определить, была ли на самом деле найдена подстрока.
В следующем примере извлекается второе слово из двух слов. Он создает 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
Вы попытались извлечь подстроку, которая находится за пределами диапазона текущей строки.
Методы, извлекающие подстроки, требуют указания начальной позиции подстроки и для подстрок, которые не продолжаются до конца строки, число символов в подстроке. Обратите внимание, что это не индекс последнего символа в подстроке.
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.MaxValue. Но поскольку аргумент измерения в следующем примере имеет отрицательное значение, метод создает 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 метод вызывается из нескольких потоков. Кроме того, основной или основной поток предполагает, что коллекция полностью заполнена семью элементами при итерации его элементов.Строка
msg
, сцепленная из нескольких потоков.
Чтобы устранить ошибку, убедитесь, что доступ к общему состоянию осуществляется потокобезопасно, как показано ниже.
Если приложение использует массив или объект коллекции, рекомендуется использовать потокобезопасный класс коллекции, например типы в System.Collections.Concurrent пространстве имен или System.Collections.Immutable внеполосный выпуск.
Убедитесь, что доступ к общим состояниям (т. е. к ресурсам, доступ к которым может осуществляться несколькими потоками) осуществляется потокобезопасно, чтобы только один поток одновременно получил монопольный доступ к ресурсам. Для синхронизации доступа к ресурсам можно синхронизировать большое количество классов, таких как CountdownEvent, InterlockedMonitorи Mutexт. е. Дополнительные сведения см. в разделе "Потоки". Кроме того, поддержка языков доступна с помощью оператора lock в C# и конструкции SyncLock в Visual Basic.
В следующем примере рассматриваются 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 использует COR_E_ARGUMENTOUTOFRANGE HRESULT, который имеет значение 0x80131502.
Список начальных значений свойств для экземпляра 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) |