ArgumentOutOfRangeException 클래스
정의
중요
일부 정보는 릴리스되기 전에 상당 부분 수정될 수 있는 시험판 제품과 관련이 있습니다. Microsoft는 여기에 제공된 정보에 대해 어떠한 명시적이거나 묵시적인 보증도 하지 않습니다.
인수 값이 호출된 메서드에 정의된 허용 가능한 값 범위를 벗어나면 throw되는 예외입니다.
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 throw됩니다.
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 고 인수에 필요한 값 집합의 멤버가 아닌 잘못된 값을 포함할 때 예외가 throw됩니다. 속성은 ParamName 잘못된 인수를 식별하고, ActualValue 값이 있는 경우 속성은 잘못된 값을 식별합니다.
일반적으로 개발자 오류의 ArgumentOutOfRangeException 결과입니다. 블록에서 try/catch 예외를 처리하는 대신 예외의 원인을 제거하거나 예외를 throw하는 메서드에 전달되기 전에 사용자가 메서드 호출 또는 입력으로 인수를 반환하는 경우 메서드에 전달하기 전에 인수의 유효성을 검사해야 합니다.
ArgumentOutOfRangeException 는 다음과 같은 용도로 광범위하게 사용됩니다.
및 네임스페이 System.CollectionsSystem.IO 스의 클래스입니다.
클래스입니다 Array .
클래스의 문자열 조작 메서드입니다 String .
예외가 ArgumentOutOfRangeException throw되는 조건은 다음과 같습니다.
컬렉션의 멤버를 인덱스 번호로 검색하고 있으며 인덱스 번호가 잘못되었습니다.
이것이 예외의 가장 일반적인 원인입니다 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속성이 0보다 큰지 확인합니다.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예외를 방지하려면 다음 코드 조각과 같이 컬렉션에서 항목을 검색하기 전에 반환된 인덱스가 0보다 크거나 같은지 확인하여 검색에 성공했는지 확인합니다.
// 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부터 시작하는 인덱싱을 사용하므로 컬렉션의 첫 번째 요소는 인덱스 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.IndexOfIndexOfAny, String.Insert, String.LastIndexOf, String.LastIndexOfAny, Remove) 등의 String.Substring 메서드 오버로드를 사용하려면 인덱스가 문자열 내에서 유효한 위치여야 합니다. 유효한 인덱스 범위는 0에서 1까지 String.Length 입니다.
이 ArgumentOutOfRangeException 예외의 일반적인 원인은 다음과 같습니다.
빈 문자열 또는 String.Empty. 속성이 0을 String.Length 반환하므로 인덱스로 조작하려고 하면 예외가 ArgumentOutOfRangeException throw됩니다. 다음 예제에서는 문자열의
GetFirstCharacter첫 번째 문자를 반환하는 메서드를 정의합니다. 메서드에 전달된 마지막 문자열처럼 문자열이 비어 있으면 메서드가 예외를 ArgumentOutOfRangeException throw합니다.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()문자열이 0보다 큰지 테스트하거나 메서드를 호출 IsNullOrEmpty 하여 문자열 String.Length 이 비어 있지 않은지
null여부를 확인하여 예외를 제거할 수 있습니다. 다음 코드 조각은 후자를 수행합니다. 이 경우 문자열이 비어 있거나 비어 있으면 메서드는nullGetFirstCharacterU+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 하나의 단어로만 구성되므로 포함된 공백 문자가 없는 경우 예외가 throw됩니다. 이는 메서드 호출이 검색에 실패했음을 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 이 경우 부분 문자열의 문자 수를 잘못 계산했기 때문에 일반적으로 예외가 throw됩니다. 하위 문자열의 시작 및 끝 위치를 식별하는 것과 같은 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'
양수와 0만 필요한 인수가 있는 메서드에 음수를 전달했거나 양수만 필요한 인수가 있는 메서드에 음수 또는 0을 전달했습니다.
예를 들어 이 메서드를 Array.CreateInstance(Type, Int32, Int32, Int32) 사용하려면 2차원 배열의 각 차원에 있는 요소 수를 지정해야 합니다. 각 차원의 유효한 값은 0에서 0까지 Int32.MaxValue입니다. 그러나 다음 예제의 차원 인수에는 음수 값이 있으므로 메서드는 예외를 ArgumentOutOfRangeException throw합니다.
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 완전히 채워지기 전에 예제에서 컬렉션의 7개 항목을 표시하려고 하면 throw됩니다.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 메서드는 여러 스레드에서 호출됩니다. 또한 주 또는 기본 스레드는 해당 멤버를 반복할 때 컬렉션이 7개의 요소로 완전히 채워져 있다고 가정합니다.msg여러 스레드에서 연결된 문자열입니다.
오류를 수정하려면 다음과 같이 스레드로부터 안전한 방식으로 공유 상태에 액세스해야 합니다.
앱에서 배열 또는 컬렉션 개체를 사용하는 경우 네임스페이스의 형식 System.Collections.Concurrent 또는 대역 외 릴리스와 같은 스레드로부터 안전한 컬렉션 클래스를 System.Collections.Immutable 사용하는 것이 좋습니다.
한 번에 하나의 스레드만 리소스에 단독으로 액세스할 수 있도록 공유 상태(즉, 여러 스레드에서 액세스할 수 있는 리소스)에 스레드로부터 안전한 방식으로 액세스해야 합니다. 리소스에 대한 액세스를 동기화하는 데 사용할 수 있는 클래스(예: CountdownEvent, InterlockedMonitor및Mutex)가 많습니다. 자세한 내용은 스레딩을 참조하세요. 또한 언어 지원은 C#의 lock 문과 Visual Basic의 SyncLock 구문을 통해 사용할 수 있습니다.
다음 예제에서는 이전 예제의 ArgumentOutOfRangeException 문제 및 기타 문제를 해결합니다. 개체를 개체로 바꿔 List<T> 서 컬렉션에 대한 액세스가 스레드로부터 안전한지 확인하고, 개체를 사용하여 CountdownEvent 다른 스레드가 실행된 후에만 애플리케이션 스레드가 계속되도록 하고, 잠금을 사용하여 한 번에 하나의 스레드만 변수에 액세스할
msg수 있도록 ConcurrentBag<T> 합니다.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 는 값이 0x80131502 HRESULT COR_E_ARGUMENTOUTOFRANGE 사용합니다.
ArgumentOutOfRangeException인스턴스의 초기 속성 값 목록은 ArgumentOutOfRangeException 생성자를 참조하세요.
생성자
| Name | Description |
|---|---|
| ArgumentOutOfRangeException() |
ArgumentOutOfRangeException 클래스의 새 인스턴스를 초기화합니다. |
| ArgumentOutOfRangeException(SerializationInfo, StreamingContext) |
사용되지 않음.
직렬화된 데이터를 사용하여 클래스의 새 인스턴스를 ArgumentOutOfRangeException 초기화합니다. |
| ArgumentOutOfRangeException(String, Exception) |
지정된 오류 메시지와 이 예외의 ArgumentOutOfRangeException 원인인 예외를 사용하여 클래스의 새 인스턴스를 초기화합니다. |
| ArgumentOutOfRangeException(String, Object, String) |
매개 변수 이름, 인수 값 및 지정된 오류 메시지를 사용하여 클래스의 새 인스턴스 ArgumentOutOfRangeException 를 초기화합니다. |
| ArgumentOutOfRangeException(String, String) |
이 예외를 발생시키는 매개 변수 이름과 지정된 오류 메시지를 사용하여 클래스의 새 인스턴스 ArgumentOutOfRangeException 를 초기화합니다. |
| ArgumentOutOfRangeException(String) |
이 예외를 발생시키는 매개 변수의 이름을 사용하여 클래스의 새 인스턴스 ArgumentOutOfRangeException 를 초기화합니다. |
속성
| Name | Description |
|---|---|
| ActualValue |
이 예외를 발생시키는 인수 값을 가져옵니다. |
| Data |
예외에 대한 추가 사용자 정의 정보를 제공하는 키/값 쌍의 컬렉션을 가져옵니다. (다음에서 상속됨 Exception) |
| HelpLink |
이 예외와 연결된 도움말 파일에 대한 링크를 가져오거나 설정합니다. (다음에서 상속됨 Exception) |
| HResult |
특정 예외에 할당된 코딩된 숫자 값인 HRESULT를 가져오거나 설정합니다. (다음에서 상속됨 Exception) |
| InnerException |
현재 예외를 Exception 발생시킨 인스턴스를 가져옵니다. (다음에서 상속됨 Exception) |
| Message |
잘못된 인수 값의 오류 메시지와 문자열 표현을 가져오거나 인수 값이 null인 경우 오류 메시지만 가져옵니다. |
| ParamName |
이 예외를 발생시키는 매개 변수의 이름을 가져옵니다. (다음에서 상속됨 ArgumentException) |
| Source |
오류를 발생시키는 애플리케이션 또는 개체의 이름을 가져오거나 설정합니다. (다음에서 상속됨 Exception) |
| StackTrace |
호출 스택에서 직접 실행 프레임의 문자열 표현을 가져옵니다. (다음에서 상속됨 Exception) |
| TargetSite |
현재 예외를 throw하는 메서드를 가져옵니다. (다음에서 상속됨 Exception) |
메서드
이벤트
| Name | Description |
|---|---|
| SerializeObjectState |
사용되지 않음.
예외에 대한 직렬화된 데이터를 포함하는 예외 상태 개체를 만들기 위해 예외가 serialize될 때 발생합니다. (다음에서 상속됨 Exception) |