ArgumentOutOfRangeException 類別
定義
重要
部分資訊涉及發行前產品,在發行之前可能會有大幅修改。 Microsoft 對此處提供的資訊,不做任何明確或隱含的瑕疵擔保。
當參數值超出所呼叫方法定義的允許值範圍時,拋出的例外。
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.CollectionsSystem.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: indexopen 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: indexopen 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: indexopen 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。 你可以透過確保存取索引為Count1 的最後一個元素來消除錯誤,如下方程式碼所做的。// 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、 IndexOfAnyString.IndexOf、 RemoveString.InsertString.LastIndexOfString.LastIndexOfAnyString.Substring ,允許你指定操作的起始索引,這些方法要求該索引必須是字串中的有效位置。 有效索引範圍為 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 citizenopen 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 citizenModule 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: length2open 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" arrDim 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" arrIf 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 if,範例嘗試在集合尚未完全填滿前顯示該集合中的七個項目。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? s_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(s_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(); s_msg += string.Format("Adding '{0}' to the list.\n", name); var continent = new Continent(); continent.Name = name; // Sleep to simulate retrieving remaining data. Thread.Sleep(50); continents.Add(continent); } } // 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、 Interlocked、 MonitorMutex,可用來同步資源存取。 更多資訊請參見「線程」。 此外,語言支援可透過 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 0open 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 0Imports 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 使用 HRESULT COR_E_ARGUMENTOUTOFRANGE,其值為 0x80131502。
如需查看 ArgumentOutOfRangeException 實例的初始屬性值列表,請參閱 ArgumentOutOfRangeException 的建構子。
建構函式
| 名稱 | Description |
|---|---|
| ArgumentOutOfRangeException() |
初始化 ArgumentOutOfRangeException 類別的新執行個體。 |
| ArgumentOutOfRangeException(SerializationInfo, StreamingContext) |
已淘汰.
使用串行化數據,初始化 ArgumentOutOfRangeException 類別的新實例。 |
| ArgumentOutOfRangeException(String, Exception) |
初始化一個新的類別實例 ArgumentOutOfRangeException ,並以指定的錯誤訊息及導致該例外的例外。 |
| ArgumentOutOfRangeException(String, Object, String) |
初始化一個新的類別實例 ArgumentOutOfRangeException ,包含參數名稱、參數值及指定錯誤訊息。 |
| ArgumentOutOfRangeException(String, String) |
初始化一個新的類別實例 ArgumentOutOfRangeException ,並以引起此例外的參數名稱及指定的錯誤訊息。 |
| ArgumentOutOfRangeException(String) |
初始化一個新的類別實例 ArgumentOutOfRangeException ,並以引起此例外的參數名稱。 |
屬性
| 名稱 | Description |
|---|---|
| ActualValue |
取得導致此例外的參數值。 |
| Data |
取得一組鍵值對,提供關於例外的額外使用者定義資訊。 (繼承來源 Exception) |
| HelpLink |
取得或設定與此例外相關的說明檔案連結。 (繼承來源 Exception) |
| HResult |
取得或設定 HRESULT,一個編碼的數值,指派給特定例外。 (繼承來源 Exception) |
| InnerException |
會取得 Exception 造成目前例外的實例。 (繼承來源 Exception) |
| Message |
取得錯誤訊息及無效參數值的字串表示,或僅在參數值為空時取得錯誤訊息。 |
| ParamName |
取得導致此例外的參數名稱。 (繼承來源 ArgumentException) |
| Source |
取得或設定造成錯誤之應用程式或物件的名稱。 (繼承來源 Exception) |
| StackTrace |
會取得呼叫堆疊上即時框架的字串表示。 (繼承來源 Exception) |
| TargetSite |
會取得拋出當前例外的方法。 (繼承來源 Exception) |
方法
事件
| 名稱 | Description |
|---|---|
| SerializeObjectState |
已淘汰.
當例外被序列化以建立包含該例外序列化資料的例外狀態物件時,會發生這種情況。 (繼承來源 Exception) |