InvalidOperationException 類別
定義
重要
部分資訊涉及發行前產品,在發行之前可能會有大幅修改。 Microsoft 對此處提供的資訊,不做任何明確或隱含的瑕疵擔保。
當方法呼叫對物件的目前狀態無效時所擲回的例外狀況。
public ref class InvalidOperationException : Exception
public ref class InvalidOperationException : SystemException
public class InvalidOperationException : Exception
public class InvalidOperationException : SystemException
[System.Serializable]
public class InvalidOperationException : SystemException
[System.Serializable]
[System.Runtime.InteropServices.ComVisible(true)]
public class InvalidOperationException : SystemException
type InvalidOperationException = class
inherit Exception
type InvalidOperationException = class
inherit SystemException
[<System.Serializable>]
type InvalidOperationException = class
inherit SystemException
[<System.Serializable>]
[<System.Runtime.InteropServices.ComVisible(true)>]
type InvalidOperationException = class
inherit SystemException
Public Class InvalidOperationException
Inherits Exception
Public Class InvalidOperationException
Inherits SystemException
- 繼承
- 繼承
- 衍生
- 屬性
備註
InvalidOperationException 當叫用方法失敗是因為無效引數以外的原因所造成時,就會使用 。 一般而言,當物件的狀態無法支援方法呼叫時,就會擲回它。 例如, InvalidOperationException 例外狀況是由方法擲回,例如:
IEnumerator.MoveNext 如果在建立列舉值之後修改集合的物件,則為 。 如需詳細資訊,請參閱 在反覆運算集合時變更集合。
ResourceSet.GetString 如果在進行方法呼叫之前關閉資源集,則為 。
XContainer.Add,如果要加入的物件或物件會導致不正確的結構化 XML 檔。
嘗試從不是主要或 UI 執行緒的執行緒操作 UI 的方法。
重要
InvalidOperationException因為例外狀況可以在各種不同的情況下擲回,所以請務必讀取 屬性所傳回的 Message 例外狀況訊息。
本節內容:
InvalidOperationException 例外狀況的一些常見原因
從非 UI 執行緒更新 UI 執行緒
在反覆運算集合時變更集合
排序無法比較物件的陣列或集合
將可為 Null < 的 T > 轉換成其基礎類型
在空集合上呼叫 System.Linq.Enumerable 方法
在沒有一個專案的序列上呼叫 Enumerable.Single 或 Enumerable.SingleOrDefault
動態跨應用程式域欄位存取
擲回 InvalidOperationException 例外狀況
其他資訊
InvalidOperationException 例外狀況的一些常見原因
下列各節說明如何在應用程式中擲回例外狀況的一些常見案例 InvalidOperationException 。 處理問題的方式取決於特定情況。 不過,最常見的是,例外狀況會產生開發人員錯誤,而且 InvalidOperationException 可以預期並避免例外狀況。
從非 UI 執行緒更新 UI 執行緒
通常,背景工作執行緒是用來執行一些背景工作,這些工作牽涉到收集資料以顯示在應用程式的使用者介面中。 不過, 大部分的 GUI (圖形化使用者介面) .NET 的應用程式架構,例如 Windows Forms 和 Windows Presentation Foundation (WPF) ,可讓您只從建立和管理 (主要或 UI 執行緒) 的執行緒存取 GUI 物件。 InvalidOperationException當您嘗試從 UI 執行緒以外的執行緒存取 UI 元素時,會擲回 。 下表顯示例外狀況訊息的文字。
應用程式類型 | 訊息 |
---|---|
WPF 應用程式 | 呼叫執行緒無法存取這個物件,因為不同的執行緒擁有它。 |
UWP app | 應用程式稱為已封送處理給不同執行緒的介面。 |
Windows Forms應用程式 | 跨執行緒作業無效:控制項 'TextBox1' 從建立所在的執行緒以外的執行緒存取。 |
.NET 的 UI 架構會實作 發送器 模式,其中包含一個方法來檢查 UI 元素成員的呼叫是否正在 UI 執行緒上執行,以及其他方法,以排程 UI 執行緒上的呼叫:
在 WPF 應用程式中,呼叫 Dispatcher.CheckAccess 方法來判斷方法是否在非 UI 執行緒上執行。 如果方法是在 UI 執行緒上執行,則
false
傳回 ,否則會傳回true
。 呼叫 方法的 Dispatcher.Invoke 其中一個多載,以在 UI 執行緒上排程呼叫。在 UWP app 中 CoreDispatcher.HasThreadAccess ,檢查 屬性以判斷方法是否在非 UI 執行緒上執行。 CoreDispatcher.RunAsync呼叫 方法來執行更新 UI 執行緒的委派。
在 Windows Forms 應用程式中,使用 Control.InvokeRequired 屬性來判斷方法是否在非 UI 執行緒上執行。 呼叫 方法的 Control.Invoke 其中一個多載,以執行更新 UI 執行緒的委派。
下列範例說明 InvalidOperationException 當您嘗試從建立 UI 元素以外的執行緒更新 UI 元素時所擲回的例外狀況。 每個範例都需要您建立兩個控制項:
名為 的
textBox1
文字方塊控制項。 在Windows Forms應用程式中,您應該將其 Multiline 屬性設定為true
。名為 的
threadExampleBtn
按鈕控制項。 此範例會提供按鈕Click
事件的處理常式ThreadsExampleBtn_Click
。
在每個案例中,事件處理常式都會 threadExampleBtn_Click
DoSomeWork
呼叫 方法兩次。 第一次呼叫會以同步方式執行並成功。 但是第二次呼叫,因為它會線上程集區執行緒上以非同步方式執行,所以會嘗試從非 UI 執行緒更新 UI。 這會導致 InvalidOperationException 例外狀況。
WPF 和 UWP 應用程式
private async void threadExampleBtn_Click(object sender, RoutedEventArgs e)
{
textBox1.Text = String.Empty;
textBox1.Text = "Simulating work on UI thread.\n";
DoSomeWork(20);
textBox1.Text += "Work completed...\n";
textBox1.Text += "Simulating work on non-UI thread.\n";
await Task.Run(() => DoSomeWork(1000));
textBox1.Text += "Work completed...\n";
}
private async void DoSomeWork(int milliseconds)
{
// Simulate work.
await Task.Delay(milliseconds);
// Report completion.
var msg = String.Format("Some work completed in {0} ms.\n", milliseconds);
textBox1.Text += msg;
}
Private Async Sub threadExampleBtn_Click(sender As Object, e As RoutedEventArgs) Handles threadExampleBtn.Click
textBox1.Text = String.Empty
textBox1.Text = "Simulating work on UI thread." + vbCrLf
DoSomeWork(20)
textBox1.Text += "Work completed..." + vbCrLf
textBox1.Text += "Simulating work on non-UI thread." + vbCrLf
Await Task.Factory.StartNew(Sub()
DoSomeWork(1000)
End Sub)
textBox1.Text += "Work completed..." + vbCrLf
End Sub
Private Async Sub DoSomeWork(milliseconds As Integer)
' Simulate work.
Await Task.Delay(milliseconds)
' Report completion.
Dim msg = String.Format("Some work completed in {0} ms.", milliseconds) + vbCrLf
textBox1.Text += msg
End Sub
下列版本的 DoSomeWork
方法會消除 WPF 應用程式中的例外狀況。
private async void DoSomeWork(int milliseconds)
{
// Simulate work.
await Task.Delay(milliseconds);
// Report completion.
bool uiAccess = textBox1.Dispatcher.CheckAccess();
String msg = String.Format("Some work completed in {0} ms. on {1}UI thread\n",
milliseconds, uiAccess ? String.Empty : "non-");
if (uiAccess)
textBox1.Text += msg;
else
textBox1.Dispatcher.Invoke(() => { textBox1.Text += msg; });
}
Private Async Sub DoSomeWork(milliseconds As Integer)
' Simulate work.
Await Task.Delay(milliseconds)
' Report completion.
Dim uiAccess As Boolean = textBox1.Dispatcher.CheckAccess()
Dim msg As String = String.Format("Some work completed in {0} ms. on {1}UI thread",
milliseconds, If(uiAccess, String.Empty, "non-")) +
vbCrLf
If uiAccess Then
textBox1.Text += msg
Else
textBox1.Dispatcher.Invoke( Sub() textBox1.Text += msg)
End If
End Sub
下列版本的 DoSomeWork
方法會消除 UWP app 中的例外狀況。
private async void DoSomeWork(int milliseconds)
{
// Simulate work.
await Task.Delay(milliseconds);
// Report completion.
bool uiAccess = textBox1.Dispatcher.HasThreadAccess;
String msg = String.Format("Some work completed in {0} ms. on {1}UI thread\n",
milliseconds, uiAccess ? String.Empty : "non-");
if (uiAccess)
textBox1.Text += msg;
else
await textBox1.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { textBox1.Text += msg; });
}
Private Async Sub DoSomeWork(milliseconds As Integer)
' Simulate work.
Await Task.Delay(milliseconds)
' Report completion.
Dim uiAccess As Boolean = textBox1.Dispatcher.HasThreadAccess
Dim msg As String = String.Format("Some work completed in {0} ms. on {1}UI thread" + vbCrLf,
milliseconds, If(uiAccess, String.Empty, "non-"))
If (uiAccess) Then
textBox1.Text += msg
Else
Await textBox1.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, Sub() textBox1.Text += msg)
End If
End Sub
Windows Forms 應用程式
List<String> lines = new List<String>();
private async void threadExampleBtn_Click(object sender, EventArgs e)
{
textBox1.Text = String.Empty;
lines.Clear();
lines.Add("Simulating work on UI thread.");
textBox1.Lines = lines.ToArray();
DoSomeWork(20);
lines.Add("Simulating work on non-UI thread.");
textBox1.Lines = lines.ToArray();
await Task.Run(() => DoSomeWork(1000));
lines.Add("ThreadsExampleBtn_Click completes. ");
textBox1.Lines = lines.ToArray();
}
private async void DoSomeWork(int milliseconds)
{
// simulate work
await Task.Delay(milliseconds);
// report completion
lines.Add(String.Format("Some work completed in {0} ms on UI thread.", milliseconds));
textBox1.Lines = lines.ToArray();
}
Dim lines As New List(Of String)()
Private Async Sub threadExampleBtn_Click(sender As Object, e As EventArgs) Handles threadExampleBtn.Click
textBox1.Text = String.Empty
lines.Clear()
lines.Add("Simulating work on UI thread.")
textBox1.Lines = lines.ToArray()
DoSomeWork(20)
lines.Add("Simulating work on non-UI thread.")
textBox1.Lines = lines.ToArray()
Await Task.Run(Sub() DoSomeWork(1000))
lines.Add("ThreadsExampleBtn_Click completes. ")
textBox1.Lines = lines.ToArray()
End Sub
Private Async Sub DoSomeWork(milliseconds As Integer)
' Simulate work.
Await Task.Delay(milliseconds)
' Report completion.
lines.Add(String.Format("Some work completed in {0} ms on UI thread.", milliseconds))
textBox1.Lines = lines.ToArray()
End Sub
下列版本的 DoSomeWork
方法會消除Windows Forms應用程式中的例外狀況。
private async void DoSomeWork(int milliseconds)
{
// simulate work
await Task.Delay(milliseconds);
// Report completion.
bool uiMarshal = textBox1.InvokeRequired;
String msg = String.Format("Some work completed in {0} ms. on {1}UI thread\n",
milliseconds, uiMarshal ? String.Empty : "non-");
lines.Add(msg);
if (uiMarshal) {
textBox1.Invoke(new Action(() => { textBox1.Lines = lines.ToArray(); }));
}
else {
textBox1.Lines = lines.ToArray();
}
}
Private Async Sub DoSomeWork(milliseconds As Integer)
' Simulate work.
Await Task.Delay(milliseconds)
' Report completion.
Dim uiMarshal As Boolean = textBox1.InvokeRequired
Dim msg As String = String.Format("Some work completed in {0} ms. on {1}UI thread" + vbCrLf,
milliseconds, If(uiMarshal, String.Empty, "non-"))
lines.Add(msg)
If uiMarshal Then
textBox1.Invoke(New Action(Sub() textBox1.Lines = lines.ToArray()))
Else
textBox1.Lines = lines.ToArray()
End If
End Sub
在反覆運算集合時變更集合
foreach
C#、 for...in
F# 中的 語句或 For Each
Visual Basic 中的 語句是用來逐一查看集合的成員,以及讀取或修改其個別專案。 不過,它無法用來新增或移除集合中的專案。 這樣做會擲回 InvalidOperationException 例外狀況,訊息類似「已修改集合;列舉作業可能不會執行。」
下列範例會逐一查看整數集合,嘗試將每個整數的平方加入至集合。 此範例會擲回第一 InvalidOperationException 次呼叫 方法的 List<T>.Add 。
using System;
using System.Collections.Generic;
public class Example
{
public static void Main()
{
var numbers = new List<int>() { 1, 2, 3, 4, 5 };
foreach (var number in numbers) {
int square = (int) Math.Pow(number, 2);
Console.WriteLine("{0}^{1}", number, square);
Console.WriteLine("Adding {0} to the collection...\n", square);
numbers.Add(square);
}
}
}
// The example displays the following output:
// 1^1
// Adding 1 to the collection...
//
//
// Unhandled Exception: System.InvalidOperationException: Collection was modified;
// enumeration operation may not execute.
// at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
// at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
// at Example.Main()
open System
let numbers = ResizeArray [| 1; 2; 3; 4; 5 |]
for number in numbers do
let square = Math.Pow(number, 2) |> int
printfn $"{number}^{square}"
printfn $"Adding {square} to the collection...\n"
numbers.Add square
// The example displays the following output:
// 1^1
// Adding 1 to the collection...
//
//
// Unhandled Exception: System.InvalidOperationException: Collection was modified
// enumeration operation may not execute.
// at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
// at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
// at <StartupCode$fs>.main()
Imports System.Collections.Generic
Module Example
Public Sub Main()
Dim numbers As New List(Of Integer)( { 1, 2, 3, 4, 5 } )
For Each number In numbers
Dim square As Integer = CInt(Math.Pow(number, 2))
Console.WriteLine("{0}^{1}", number, square)
Console.WriteLine("Adding {0} to the collection..." + vbCrLf,
square)
numbers.Add(square)
Next
End Sub
End Module
' The example displays the following output:
' 1^1
' Adding 1 to the collection...
'
'
' Unhandled Exception: System.InvalidOperationException: Collection was modified;
' enumeration operation may not execute.
' at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
' at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
' at Example.Main()
視您的應用程式邏輯而定,您可以使用下列兩種方式之一來消除例外狀況:
如果元素必須在逐一查看集合時加入至集合,您可以使用 F#) 語句中的 (
for..to
,而不是foreach
、for...in
或For Each
來逐一查看for
它。 下列範例會使用 for 語句,將集合中的數位平方加入集合中。using System; using System.Collections.Generic; public class Example { public static void Main() { var numbers = new List<int>() { 1, 2, 3, 4, 5 }; int upperBound = numbers.Count - 1; for (int ctr = 0; ctr <= upperBound; ctr++) { int square = (int) Math.Pow(numbers[ctr], 2); Console.WriteLine("{0}^{1}", numbers[ctr], square); Console.WriteLine("Adding {0} to the collection...\n", square); numbers.Add(square); } Console.WriteLine("Elements now in the collection: "); foreach (var number in numbers) Console.Write("{0} ", number); } } // The example displays the following output: // 1^1 // Adding 1 to the collection... // // 2^4 // Adding 4 to the collection... // // 3^9 // Adding 9 to the collection... // // 4^16 // Adding 16 to the collection... // // 5^25 // Adding 25 to the collection... // // Elements now in the collection: // 1 2 3 4 5 1 4 9 16 25
open System open System.Collections.Generic let numbers = ResizeArray [| 1; 2; 3; 4; 5 |] let upperBound = numbers.Count - 1 for i = 0 to upperBound do let square = Math.Pow(numbers[i], 2) |> int printfn $"{numbers[i]}^{square}" printfn $"Adding {square} to the collection...\n" numbers.Add square printfn "Elements now in the collection: " for number in numbers do printf $"{number} " // The example displays the following output: // 1^1 // Adding 1 to the collection... // // 2^4 // Adding 4 to the collection... // // 3^9 // Adding 9 to the collection... // // 4^16 // Adding 16 to the collection... // // 5^25 // Adding 25 to the collection... // // Elements now in the collection: // 1 2 3 4 5 1 4 9 16 25
Imports System.Collections.Generic Module Example Public Sub Main() Dim numbers As New List(Of Integer)( { 1, 2, 3, 4, 5 } ) Dim upperBound = numbers.Count - 1 For ctr As Integer = 0 To upperBound Dim square As Integer = CInt(Math.Pow(numbers(ctr), 2)) Console.WriteLine("{0}^{1}", numbers(ctr), square) Console.WriteLine("Adding {0} to the collection..." + vbCrLf, square) numbers.Add(square) Next Console.WriteLine("Elements now in the collection: ") For Each number In numbers Console.Write("{0} ", number) Next End Sub End Module ' The example displays the following output: ' 1^1 ' Adding 1 to the collection... ' ' 2^4 ' Adding 4 to the collection... ' ' 3^9 ' Adding 9 to the collection... ' ' 4^16 ' Adding 16 to the collection... ' ' 5^25 ' Adding 25 to the collection... ' ' Elements now in the collection: ' 1 2 3 4 5 1 4 9 16 25
請注意,您必須先建立反復專案數目,再使用迴圈內部的計數器來適當地結束迴圈、逐一查看迴圈、從
Count
- 1 到 0,或如範例所示,將陣列中的專案數目指派給變數,並使用它建立迴圈的上限。 否則,如果在每次反覆運算時將專案新增至集合,則會產生無限迴圈。如果不需要在反覆運算集合時將元素新增至集合,您可以將專案儲存在反覆運算集合完成時所新增的暫存集合中。 下列範例會使用此方法,將集合中的數位平方加入暫存集合,然後將集合合併成單一陣列物件。
using System; using System.Collections.Generic; public class Example { public static void Main() { var numbers = new List<int>() { 1, 2, 3, 4, 5 }; var temp = new List<int>(); // Square each number and store it in a temporary collection. foreach (var number in numbers) { int square = (int) Math.Pow(number, 2); temp.Add(square); } // Combine the numbers into a single array. int[] combined = new int[numbers.Count + temp.Count]; Array.Copy(numbers.ToArray(), 0, combined, 0, numbers.Count); Array.Copy(temp.ToArray(), 0, combined, numbers.Count, temp.Count); // Iterate the array. foreach (var value in combined) Console.Write("{0} ", value); } } // The example displays the following output: // 1 2 3 4 5 1 4 9 16 25
open System open System.Collections.Generic let numbers = ResizeArray [| 1; 2; 3; 4; 5 |] let temp = ResizeArray() // Square each number and store it in a temporary collection. for number in numbers do let square = Math.Pow(number, 2) |> int temp.Add square // Combine the numbers into a single array. let combined = Array.zeroCreate<int> (numbers.Count + temp.Count) Array.Copy(numbers.ToArray(), 0, combined, 0, numbers.Count) Array.Copy(temp.ToArray(), 0, combined, numbers.Count, temp.Count) // Iterate the array. for value in combined do printf $"{value} " // The example displays the following output: // 1 2 3 4 5 1 4 9 16 25
Imports System.Collections.Generic Module Example Public Sub Main() Dim numbers As New List(Of Integer)( { 1, 2, 3, 4, 5 } ) Dim temp As New List(Of Integer)() ' Square each number and store it in a temporary collection. For Each number In numbers Dim square As Integer = CInt(Math.Pow(number, 2)) temp.Add(square) Next ' Combine the numbers into a single array. Dim combined(numbers.Count + temp.Count - 1) As Integer Array.Copy(numbers.ToArray(), 0, combined, 0, numbers.Count) Array.Copy(temp.ToArray(), 0, combined, numbers.Count, temp.Count) ' Iterate the array. For Each value In combined Console.Write("{0} ", value) Next End Sub End Module ' The example displays the following output: ' 1 2 3 4 5 1 4 9 16 25
排序無法比較物件的陣列或集合
一般用途的排序方法,例如 Array.Sort(Array) 方法或 List<T>.Sort() 方法,通常需要至少一個要排序 IComparable<T> 的物件實作 或 IComparable 介面。 如果沒有,則無法排序集合或陣列,而且方法會 InvalidOperationException 擲回例外狀況。 下列範例會定義 類別、將兩 Person
個 Person
物件儲存在泛型 List<T> 物件中,並嘗試加以排序。 如範例的輸出所示,對 方法的 List<T>.Sort() 呼叫會 InvalidOperationException 擲回 。
using System;
using System.Collections.Generic;
public class Person
{
public Person(String fName, String lName)
{
FirstName = fName;
LastName = lName;
}
public String FirstName { get; set; }
public String LastName { get; set; }
}
public class Example
{
public static void Main()
{
var people = new List<Person>();
people.Add(new Person("John", "Doe"));
people.Add(new Person("Jane", "Doe"));
people.Sort();
foreach (var person in people)
Console.WriteLine("{0} {1}", person.FirstName, person.LastName);
}
}
// The example displays the following output:
// Unhandled Exception: System.InvalidOperationException: Failed to compare two elements in the array. --->
// System.ArgumentException: At least one object must implement IComparable.
// at System.Collections.Comparer.Compare(Object a, Object b)
// at System.Collections.Generic.ArraySortHelper`1.SwapIfGreater(T[] keys, IComparer`1 comparer, Int32 a, Int32 b)
// at System.Collections.Generic.ArraySortHelper`1.DepthLimitedQuickSort(T[] keys, Int32 left, Int32 right, IComparer`1 comparer, Int32 depthLimit)
// at System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index, Int32 length, IComparer`1 comparer)
// --- End of inner exception stack trace ---
// at System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index, Int32 length, IComparer`1 comparer)
// at System.Array.Sort[T](T[] array, Int32 index, Int32 length, IComparer`1 comparer)
// at System.Collections.Generic.List`1.Sort(Int32 index, Int32 count, IComparer`1 comparer)
// at Example.Main()
type Person(firstName: string, lastName: string) =
member val FirstName = firstName with get, set
member val LastName = lastName with get, set
let people = ResizeArray()
people.Add(Person("John", "Doe"))
people.Add(Person("Jane", "Doe"))
people.Sort()
for person in people do
printfn $"{person.FirstName} {person.LastName}"
// The example displays the following output:
// Unhandled Exception: System.InvalidOperationException: Failed to compare two elements in the array. --->
// System.ArgumentException: At least one object must implement IComparable.
// at System.Collections.Comparer.Compare(Object a, Object b)
// at System.Collections.Generic.ArraySortHelper`1.SwapIfGreater(T[] keys, IComparer`1 comparer, Int32 a, Int32 b)
// at System.Collections.Generic.ArraySortHelper`1.DepthLimitedQuickSort(T[] keys, Int32 left, Int32 right, IComparer`1 comparer, Int32 depthLimit)
// at System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index, Int32 length, IComparer`1 comparer)
// --- End of inner exception stack trace ---
// at System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index, Int32 length, IComparer`1 comparer)
// at System.Array.Sort[T](T[] array, Int32 index, Int32 length, IComparer`1 comparer)
// at System.Collections.Generic.List`1.Sort(Int32 index, Int32 count, IComparer`1 comparer)
// at <StartupCode$fs>.main()
Imports System.Collections.Generic
Public Class Person
Public Sub New(fName As String, lName As String)
FirstName = fName
LastName = lName
End Sub
Public Property FirstName As String
Public Property LastName As String
End Class
Module Example
Public Sub Main()
Dim people As New List(Of Person)()
people.Add(New Person("John", "Doe"))
people.Add(New Person("Jane", "Doe"))
people.Sort()
For Each person In people
Console.WriteLine("{0} {1}", person.FirstName, person.LastName)
Next
End Sub
End Module
' The example displays the following output:
' Unhandled Exception: System.InvalidOperationException: Failed to compare two elements in the array. --->
' System.ArgumentException: At least one object must implement IComparable.
' at System.Collections.Comparer.Compare(Object a, Object b)
' at System.Collections.Generic.ArraySortHelper`1.SwapIfGreater(T[] keys, IComparer`1 comparer, Int32 a, Int32 b)
' at System.Collections.Generic.ArraySortHelper`1.DepthLimitedQuickSort(T[] keys, Int32 left, Int32 right, IComparer`1 comparer, Int32 depthLimit)
' at System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index, Int32 length, IComparer`1 comparer)
' --- End of inner exception stack trace ---
' at System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index, Int32 length, IComparer`1 comparer)
' at System.Array.Sort[T](T[] array, Int32 index, Int32 length, IComparer`1 comparer)
' at System.Collections.Generic.List`1.Sort(Int32 index, Int32 count, IComparer`1 comparer)
' at Example.Main()
您可以使用下列三種方式之一來消除例外狀況:
如果您擁有嘗試排序的類型 (,也就是說,如果您控制其原始程式碼) ,您可以修改它來實 IComparable<T> 作 或 IComparable 介面。 這需要您實 IComparable<T>.CompareTo 作 或 CompareTo 方法。 將介面實作新增至現有類型不是中斷性變更。
下列範例會使用此方法來提供 IComparable<T> 類別的實作
Person
。 您仍然可以呼叫集合或陣列的一般排序方法,而且當範例的輸出顯示時,集合會成功排序。using System; using System.Collections.Generic; public class Person : IComparable<Person> { public Person(String fName, String lName) { FirstName = fName; LastName = lName; } public String FirstName { get; set; } public String LastName { get; set; } public int CompareTo(Person other) { return String.Format("{0} {1}", LastName, FirstName). CompareTo(String.Format("{0} {1}", other.LastName, other.FirstName)); } } public class Example { public static void Main() { var people = new List<Person>(); people.Add(new Person("John", "Doe")); people.Add(new Person("Jane", "Doe")); people.Sort(); foreach (var person in people) Console.WriteLine("{0} {1}", person.FirstName, person.LastName); } } // The example displays the following output: // Jane Doe // John Doe
open System type Person(firstName: string, lastName: string) = member val FirstName = firstName with get, set member val LastName = lastName with get, set interface IComparable<Person> with member this.CompareTo(other) = compare $"{this.LastName} {this.FirstName}" $"{other.LastName} {other.FirstName}" let people = ResizeArray() people.Add(new Person("John", "Doe")) people.Add(new Person("Jane", "Doe")) people.Sort() for person in people do printfn $"{person.FirstName} {person.LastName}" // The example displays the following output: // Jane Doe // John Doe
Imports System.Collections.Generic Public Class Person : Implements IComparable(Of Person) Public Sub New(fName As String, lName As String) FirstName = fName LastName = lName End Sub Public Property FirstName As String Public Property LastName As String Public Function CompareTo(other As Person) As Integer _ Implements IComparable(Of Person).CompareTo Return String.Format("{0} {1}", LastName, FirstName). CompareTo(String.Format("{0} {1}", other.LastName, other.FirstName)) End Function End Class Module Example Public Sub Main() Dim people As New List(Of Person)() people.Add(New Person("John", "Doe")) people.Add(New Person("Jane", "Doe")) people.Sort() For Each person In people Console.WriteLine("{0} {1}", person.FirstName, person.LastName) Next End Sub End Module ' The example displays the following output: ' Jane Doe ' John Doe
如果您無法修改您嘗試排序之類型的原始程式碼,您可以定義實作 介面的特殊用途排序類別 IComparer<T> 。 您可以呼叫包含 IComparer<T> 參數的方法
Sort
多載。 如果您想要開發可根據多個準則排序物件的特製化排序類別,此方法特別有用。下列範例會藉由開發用來排序
Person
集合的自訂PersonComparer
類別,來使用 方法。 然後,它會將這個類別的實例傳遞至 List<T>.Sort(IComparer<T>) 方法。using System; using System.Collections.Generic; public class Person { public Person(String fName, String lName) { FirstName = fName; LastName = lName; } public String FirstName { get; set; } public String LastName { get; set; } } public class PersonComparer : IComparer<Person> { public int Compare(Person x, Person y) { return String.Format("{0} {1}", x.LastName, x.FirstName). CompareTo(String.Format("{0} {1}", y.LastName, y.FirstName)); } } public class Example { public static void Main() { var people = new List<Person>(); people.Add(new Person("John", "Doe")); people.Add(new Person("Jane", "Doe")); people.Sort(new PersonComparer()); foreach (var person in people) Console.WriteLine("{0} {1}", person.FirstName, person.LastName); } } // The example displays the following output: // Jane Doe // John Doe
open System open System.Collections.Generic type Person(firstName, lastName) = member val FirstName = firstName with get, set member val LastName = lastName with get, set type PersonComparer() = interface IComparer<Person> with member _.Compare(x: Person, y: Person) = $"{x.LastName} {x.FirstName}".CompareTo $"{y.LastName} {y.FirstName}" let people = ResizeArray() people.Add(Person("John", "Doe")) people.Add(Person("Jane", "Doe")) people.Sort(PersonComparer()) for person in people do printfn $"{person.FirstName} {person.LastName}" // The example displays the following output: // Jane Doe // John Doe
Imports System.Collections.Generic Public Class Person Public Sub New(fName As String, lName As String) FirstName = fName LastName = lName End Sub Public Property FirstName As String Public Property LastName As String End Class Public Class PersonComparer : Implements IComparer(Of Person) Public Function Compare(x As Person, y As Person) As Integer _ Implements IComparer(Of Person).Compare Return String.Format("{0} {1}", x.LastName, x.FirstName). CompareTo(String.Format("{0} {1}", y.LastName, y.FirstName)) End Function End Class Module Example Public Sub Main() Dim people As New List(Of Person)() people.Add(New Person("John", "Doe")) people.Add(New Person("Jane", "Doe")) people.Sort(New PersonComparer()) For Each person In people Console.WriteLine("{0} {1}", person.FirstName, person.LastName) Next End Sub End Module ' The example displays the following output: ' Jane Doe ' John Doe
如果您無法修改您嘗試排序之類型的原始程式碼,您可以建立 Comparison<T> 委派來執行排序。 委派簽章為
Function Comparison(Of T)(x As T, y As T) As Integer
int Comparison<T>(T x, T y)
下列範例會藉由定義
PersonComparison
符合 Comparison<T> 委派簽章的方法,來使用 方法。 然後,它會將此委派傳遞至 List<T>.Sort(Comparison<T>) 方法。using System; using System.Collections.Generic; public class Person { public Person(String fName, String lName) { FirstName = fName; LastName = lName; } public String FirstName { get; set; } public String LastName { get; set; } } public class Example { public static void Main() { var people = new List<Person>(); people.Add(new Person("John", "Doe")); people.Add(new Person("Jane", "Doe")); people.Sort(PersonComparison); foreach (var person in people) Console.WriteLine("{0} {1}", person.FirstName, person.LastName); } public static int PersonComparison(Person x, Person y) { return String.Format("{0} {1}", x.LastName, x.FirstName). CompareTo(String.Format("{0} {1}", y.LastName, y.FirstName)); } } // The example displays the following output: // Jane Doe // John Doe
open System open System.Collections.Generic type Person(firstName, lastName) = member val FirstName = firstName with get, set member val LastName = lastName with get, set let personComparison (x: Person) (y: Person) = $"{x.LastName} {x.FirstName}".CompareTo $"{y.LastName} {y.FirstName}" let people = ResizeArray() people.Add(Person("John", "Doe")) people.Add(Person("Jane", "Doe")) people.Sort personComparison for person in people do printfn $"{person.FirstName} {person.LastName}" // The example displays the following output: // Jane Doe // John Doe
Imports System.Collections.Generic Public Class Person Public Sub New(fName As String, lName As String) FirstName = fName LastName = lName End Sub Public Property FirstName As String Public Property LastName As String End Class Module Example Public Sub Main() Dim people As New List(Of Person)() people.Add(New Person("John", "Doe")) people.Add(New Person("Jane", "Doe")) people.Sort(AddressOf PersonComparison) For Each person In people Console.WriteLine("{0} {1}", person.FirstName, person.LastName) Next End Sub Public Function PersonComparison(x As Person, y As Person) As Integer Return String.Format("{0} {1}", x.LastName, x.FirstName). CompareTo(String.Format("{0} {1}", y.LastName, y.FirstName)) End Function End Module ' The example displays the following output: ' Jane Doe ' John Doe
將可為 Null <T> 的轉換為其基礎類型
嘗試將值轉換成 Nullable<T> null
其基礎類型會 InvalidOperationException 擲回例外狀況,並顯示錯誤訊息:「可為 Null 的物件必須有值。
下列範例 InvalidOperationException 會在嘗試逐一查看包含 Nullable(Of Integer)
值的陣列時擲回例外狀況。
using System;
using System.Linq;
public class Example
{
public static void Main()
{
var queryResult = new int?[] { 1, 2, null, 4 };
var map = queryResult.Select(nullableInt => (int)nullableInt);
// Display list.
foreach (var num in map)
Console.Write("{0} ", num);
Console.WriteLine();
}
}
// The example displays the following output:
// 1 2
// Unhandled Exception: System.InvalidOperationException: Nullable object must have a value.
// at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
// at Example.<Main>b__0(Nullable`1 nullableInt)
// at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
// at Example.Main()
open System
open System.Linq
let queryResult = [| Nullable 1; Nullable 2; Nullable(); Nullable 4 |]
let map = queryResult.Select(fun nullableInt -> nullableInt.Value)
// Display list.
for num in map do
printf $"{num} "
printfn ""
// The example displays the following output:
// 1 2
// Unhandled Exception: System.InvalidOperationException: Nullable object must have a value.
// at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
// at Example.<Main>b__0(Nullable`1 nullableInt)
// at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
// at <StartupCode$fs>.main()
Imports System.Linq
Module Example
Public Sub Main()
Dim queryResult = New Integer?() { 1, 2, Nothing, 4 }
Dim map = queryResult.Select(Function(nullableInt) CInt(nullableInt))
' Display list.
For Each num In map
Console.Write("{0} ", num)
Next
Console.WriteLine()
End Sub
End Module
' The example displays thIe following output:
' 1 2
' Unhandled Exception: System.InvalidOperationException: Nullable object must have a value.
' at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
' at Example.<Main>b__0(Nullable`1 nullableInt)
' at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
' at Example.Main()
若要防止例外狀況:
使用 Nullable<T>.HasValue 屬性只選取不是
null
的元素。呼叫其中 Nullable<T>.GetValueOrDefault 一個多載,以提供值的預設值
null
。
下列範例會執行這兩個動作來避免例外狀況 InvalidOperationException 。
using System;
using System.Linq;
public class Example
{
public static void Main()
{
var queryResult = new int?[] { 1, 2, null, 4 };
var numbers = queryResult.Select(nullableInt => (int)nullableInt.GetValueOrDefault());
// Display list using Nullable<int>.HasValue.
foreach (var number in numbers)
Console.Write("{0} ", number);
Console.WriteLine();
numbers = queryResult.Select(nullableInt => (int) (nullableInt.HasValue ? nullableInt : -1));
// Display list using Nullable<int>.GetValueOrDefault.
foreach (var number in numbers)
Console.Write("{0} ", number);
Console.WriteLine();
}
}
// The example displays the following output:
// 1 2 0 4
// 1 2 -1 4
open System
open System.Linq
let queryResult = [| Nullable 1; Nullable 2; Nullable(); Nullable 4 |]
let numbers = queryResult.Select(fun nullableInt -> nullableInt.GetValueOrDefault())
// Display list using Nullable<int>.HasValue.
for number in numbers do
printf $"{number} "
printfn ""
let numbers2 = queryResult.Select(fun nullableInt -> if nullableInt.HasValue then nullableInt.Value else -1)
// Display list using Nullable<int>.GetValueOrDefault.
for number in numbers2 do
printf $"{number} "
printfn ""
// The example displays the following output:
// 1 2 0 4
// 1 2 -1 4
Imports System.Linq
Module Example
Public Sub Main()
Dim queryResult = New Integer?() { 1, 2, Nothing, 4 }
Dim numbers = queryResult.Select(Function(nullableInt) _
CInt(nullableInt.GetValueOrDefault()))
' Display list.
For Each number In numbers
Console.Write("{0} ", number)
Next
Console.WriteLine()
' Use -1 to indicate a missing values.
numbers = queryResult.Select(Function(nullableInt) _
CInt(If(nullableInt.HasValue, nullableInt, -1)))
' Display list.
For Each number In numbers
Console.Write("{0} ", number)
Next
Console.WriteLine()
End Sub
End Module
' The example displays the following output:
' 1 2 0 4
' 1 2 -1 4
在空集合上呼叫 System.Linq.Enumerable 方法
Enumerable.Aggregate、 Enumerable.Average 、 Enumerable.First 、 Enumerable.Last 、 Enumerable.Max Enumerable.Min 、、 Enumerable.Single 和 Enumerable.SingleOrDefault 方法會在序列上執行作業,並傳回單一結果。 當序列是空的時,這些方法的某些多載會擲 InvalidOperationException 回例外狀況,而其他多載則會傳回 null
。 當序列包含一個以上的專案時,方法 Enumerable.SingleOrDefault 也會擲回 InvalidOperationException 例外狀況。
注意
大部分擲回 InvalidOperationException 例外狀況的方法都是多載。 請確定您瞭解您選擇的多載行為。
下表列出呼叫某些 System.Linq.Enumerable 方法所擲回之例外狀況物件中的 InvalidOperationException 例外狀況訊息。
方法 | 訊息 |
---|---|
Aggregate Average Last Max Min |
序列不包含任何元素 |
First |
序列未包含相符的專案 |
Single SingleOrDefault |
序列包含一個以上的相符專案 |
排除或處理例外狀況的方式取決於您應用程式的假設,以及您呼叫的特定方法。
當您刻意呼叫其中一個方法而不檢查空序列時,您會假設序列不是空的,而且空序列是非預期的發生。 在此情況下,攔截或重新擲回例外狀況是適當的 。
如果您無法檢查空序列是否不小心,您可以呼叫多載的 Enumerable.Any 其中一個多載,以判斷序列是否包含任何元素。
提示
Enumerable.Any<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>)如果要處理的資料可能包含大量元素,或產生序列的作業成本很高,則呼叫 方法後,就可以改善效能。
如果您已呼叫 、 Enumerable.Last 、 或 Enumerable.Single 之類的 Enumerable.First 方法,您可以替代替代方法,例如 Enumerable.FirstOrDefault 、 Enumerable.LastOrDefault 或 Enumerable.SingleOrDefault ,以傳回預設值,而不是序列的成員。
這些範例會提供其他詳細資料。
下列範例會 Enumerable.Average 使用 方法來計算其值大於 4 的序列平均值。 由於原始陣列的值未超過 4,因此序列中不會包含任何值,而且 方法會 InvalidOperationException 擲回例外狀況。
using System;
using System.Linq;
public class Example
{
public static void Main()
{
int[] data = { 1, 2, 3, 4 };
var average = data.Where(num => num > 4).Average();
Console.Write("The average of numbers greater than 4 is {0}",
average);
}
}
// The example displays the following output:
// Unhandled Exception: System.InvalidOperationException: Sequence contains no elements
// at System.Linq.Enumerable.Average(IEnumerable`1 source)
// at Example.Main()
open System
open System.Linq
let data = [| 1; 2; 3; 4 |]
let average =
data.Where(fun num -> num > 4).Average();
printfn $"The average of numbers greater than 4 is {average}"
// The example displays the following output:
// Unhandled Exception: System.InvalidOperationException: Sequence contains no elements
// at System.Linq.Enumerable.Average(IEnumerable`1 source)
// at <StartupCode$fs>.main()
Imports System.Linq
Module Example
Public Sub Main()
Dim data() As Integer = { 1, 2, 3, 4 }
Dim average = data.Where(Function(num) num > 4).Average()
Console.Write("The average of numbers greater than 4 is {0}",
average)
End Sub
End Module
' The example displays the following output:
' Unhandled Exception: System.InvalidOperationException: Sequence contains no elements
' at System.Linq.Enumerable.Average(IEnumerable`1 source)
' at Example.Main()
您可以藉由呼叫 Any 方法來判斷序列是否包含任何元素,然後再呼叫處理序列的方法,藉此消除例外狀況,如下列範例所示。
using System;
using System.Linq;
public class Example
{
public static void Main()
{
int[] dbQueryResults = { 1, 2, 3, 4 };
var moreThan4 = dbQueryResults.Where(num => num > 4);
if(moreThan4.Any())
Console.WriteLine("Average value of numbers greater than 4: {0}:",
moreThan4.Average());
else
// handle empty collection
Console.WriteLine("The dataset has no values greater than 4.");
}
}
// The example displays the following output:
// The dataset has no values greater than 4.
open System
open System.Linq
let dbQueryResults = [| 1; 2; 3; 4 |]
let moreThan4 =
dbQueryResults.Where(fun num -> num > 4)
if moreThan4.Any() then
printfn $"Average value of numbers greater than 4: {moreThan4.Average()}:"
else
// handle empty collection
printfn "The dataset has no values greater than 4."
// The example displays the following output:
// The dataset has no values greater than 4.
Imports System.Linq
Module Example
Public Sub Main()
Dim dbQueryResults() As Integer = { 1, 2, 3, 4 }
Dim moreThan4 = dbQueryResults.Where(Function(num) num > 4)
If moreThan4.Any() Then
Console.WriteLine("Average value of numbers greater than 4: {0}:",
moreThan4.Average())
Else
' Handle empty collection.
Console.WriteLine("The dataset has no values greater than 4.")
End If
End Sub
End Module
' The example displays the following output:
' The dataset has no values greater than 4.
方法 Enumerable.First 會傳回序列中的第一個專案,或序列中符合指定條件的第一個專案。 如果序列是空的,因此沒有第一個專案,則會擲回 InvalidOperationException 例外狀況。
在下列範例中 Enumerable.First<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>) ,方法會 InvalidOperationException 擲回例外狀況,因為 dbQueryResults 陣列不包含大於 4 的專案。
using System;
using System.Linq;
public class Example
{
public static void Main()
{
int[] dbQueryResults = { 1, 2, 3, 4 };
var firstNum = dbQueryResults.First(n => n > 4);
Console.WriteLine("The first value greater than 4 is {0}",
firstNum);
}
}
// The example displays the following output:
// Unhandled Exception: System.InvalidOperationException:
// Sequence contains no matching element
// at System.Linq.Enumerable.First[TSource](IEnumerable`1 source, Func`2 predicate)
// at Example.Main()
open System
open System.Linq
let dbQueryResults = [| 1; 2; 3; 4 |]
let firstNum = dbQueryResults.First(fun n -> n > 4)
printfn $"The first value greater than 4 is {firstNum}"
// The example displays the following output:
// Unhandled Exception: System.InvalidOperationException:
// Sequence contains no matching element
// at System.Linq.Enumerable.First[TSource](IEnumerable`1 source, Func`2 predicate)
// at <StartupCode$fs>.main()
Imports System.Linq
Module Example
Public Sub Main()
Dim dbQueryResults() As Integer = { 1, 2, 3, 4 }
Dim firstNum = dbQueryResults.First(Function(n) n > 4)
Console.WriteLine("The first value greater than 4 is {0}",
firstNum)
End Sub
End Module
' The example displays the following output:
' Unhandled Exception: System.InvalidOperationException:
' Sequence contains no matching element
' at System.Linq.Enumerable.First[TSource](IEnumerable`1 source, Func`2 predicate)
' at Example.Main()
您可以呼叫 Enumerable.FirstOrDefault 方法,而不是 Enumerable.First 傳回指定的或預設值。 如果方法在序列中找不到第一個專案,它會傳回該資料類型的預設值。 預設值為 null
參考型別、數值資料類型為零,以及 DateTime.MinValue 型別為 DateTime 零。
注意
解譯 方法所 Enumerable.FirstOrDefault 傳回的值通常很複雜,因為類型的預設值可以是序列中的有效值。 在此情況下,您會呼叫 Enumerable.Any 方法來判斷序列在呼叫 Enumerable.First 方法之前是否具有有效的成員。
下列範例會 Enumerable.FirstOrDefault<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>) 呼叫 方法,以防止 InvalidOperationException 在上一個範例中擲回的例外狀況。
using System;
using System.Linq;
public class Example
{
public static void Main()
{
int[] dbQueryResults = { 1, 2, 3, 4 };
var firstNum = dbQueryResults.FirstOrDefault(n => n > 4);
if (firstNum == 0)
Console.WriteLine("No value is greater than 4.");
else
Console.WriteLine("The first value greater than 4 is {0}",
firstNum);
}
}
// The example displays the following output:
// No value is greater than 4.
open System
open System.Linq
let dbQueryResults = [| 1; 2; 3; 4 |]
let firstNum = dbQueryResults.FirstOrDefault(fun n -> n > 4)
if firstNum = 0 then
printfn "No value is greater than 4."
else
printfn $"The first value greater than 4 is {firstNum}"
// The example displays the following output:
// No value is greater than 4.
Imports System.Linq
Module Example
Public Sub Main()
Dim dbQueryResults() As Integer = { 1, 2, 3, 4 }
Dim firstNum = dbQueryResults.FirstOrDefault(Function(n) n > 4)
If firstNum = 0 Then
Console.WriteLIne("No value is greater than 4.")
Else
Console.WriteLine("The first value greater than 4 is {0}",
firstNum)
End If
End Sub
End Module
' The example displays the following output:
' No value is greater than 4.
在沒有一個專案的序列上呼叫 Enumerable.Single 或 Enumerable.SingleOrDefault
方法 Enumerable.Single 會傳回序列的唯一專案,或是符合指定條件之序列的唯一專案。 如果序列中沒有任何專案,或有多個元素,則方法會 InvalidOperationException 擲回例外狀況。
您可以使用 Enumerable.SingleOrDefault 方法傳回預設值,而不是在序列不包含任何元素時擲回例外狀況。 不過,當序列包含多個元素時, Enumerable.SingleOrDefault 方法仍會擲回 InvalidOperationException 例外狀況。
下表列出呼叫 InvalidOperationException Enumerable.Single 和 Enumerable.SingleOrDefault 方法所擲回之例外狀況物件中的例外狀況訊息。
方法 | 訊息 |
---|---|
Single |
序列未包含相符的專案 |
Single SingleOrDefault |
序列包含一個以上的相符專案 |
在下列範例中,呼叫 Enumerable.Single 方法會擲回 InvalidOperationException 例外狀況,因為序列沒有大於 4 的專案。
using System;
using System.Linq;
public class Example
{
public static void Main()
{
int[] dbQueryResults = { 1, 2, 3, 4 };
var singleObject = dbQueryResults.Single(value => value > 4);
// Display results.
Console.WriteLine("{0} is the only value greater than 4", singleObject);
}
}
// The example displays the following output:
// Unhandled Exception: System.InvalidOperationException:
// Sequence contains no matching element
// at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source, Func`2 predicate)
// at Example.Main()
open System
open System.Linq
let dbQueryResults = [| 1; 2; 3; 4 |]
let singleObject = dbQueryResults.Single(fun value -> value > 4)
// Display results.
printfn $"{singleObject} is the only value greater than 4"
// The example displays the following output:
// Unhandled Exception: System.InvalidOperationException:
// Sequence contains no matching element
// at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source, Func`2 predicate)
// at <StartupCode$fs>.main()
Imports System.Linq
Module Example
Public Sub Main()
Dim dbQueryResults() As Integer = { 1, 2, 3, 4 }
Dim singleObject = dbQueryResults.Single(Function(value) value > 4)
' Display results.
Console.WriteLine("{0} is the only value greater than 4",
singleObject)
End Sub
End Module
' The example displays the following output:
' Unhandled Exception: System.InvalidOperationException:
' Sequence contains no matching element
' at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source, Func`2 predicate)
' at Example.Main()
下列範例會藉由呼叫 方法,嘗試避免 InvalidOperationException 在序列是空的時擲回例外 Enumerable.SingleOrDefault 狀況。 不過,因為這個序列會傳回多個值大於 2 的專案,所以也會擲 InvalidOperationException 回例外狀況。
using System;
using System.Linq;
public class Example
{
public static void Main()
{
int[] dbQueryResults = { 1, 2, 3, 4 };
var singleObject = dbQueryResults.SingleOrDefault(value => value > 2);
if (singleObject != 0)
Console.WriteLine("{0} is the only value greater than 2",
singleObject);
else
// Handle an empty collection.
Console.WriteLine("No value is greater than 2");
}
}
// The example displays the following output:
// Unhandled Exception: System.InvalidOperationException:
// Sequence contains more than one matching element
// at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source, Func`2 predicate)
// at Example.Main()
open System
open System.Linq
let dbQueryResults = [| 1; 2; 3; 4 |]
let singleObject = dbQueryResults.SingleOrDefault(fun value -> value > 2)
if singleObject <> 0 then
printfn $"{singleObject} is the only value greater than 2"
else
// Handle an empty collection.
printfn "No value is greater than 2"
// The example displays the following output:
// Unhandled Exception: System.InvalidOperationException:
// Sequence contains more than one matching element
// at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source, Func`2 predicate)
// at <StartupCode$fs>.main()
Imports System.Linq
Module Example
Public Sub Main()
Dim dbQueryResults() As Integer = { 1, 2, 3, 4 }
Dim singleObject = dbQueryResults.SingleOrDefault(Function(value) value > 2)
If singleObject <> 0 Then
Console.WriteLine("{0} is the only value greater than 2",
singleObject)
Else
' Handle an empty collection.
Console.WriteLine("No value is greater than 2")
End If
End Sub
End Module
' The example displays the following output:
' Unhandled Exception: System.InvalidOperationException:
' Sequence contains more than one matching element
' at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source, Func`2 predicate)
' at Example.Main()
Enumerable.Single呼叫 方法會假設序列或符合指定準則的序列只包含一個專案。 Enumerable.SingleOrDefault 假設具有零或一個結果的序列,但不再假設。 如果此假設是您部分的刻意假設,而且不符合這些條件,請適當地重新擲回或攔截產生的 InvalidOperationException 。 否則,或者,如果您預期不正確條件會以某種頻率發生,您應該考慮使用一些其他 Enumerable 方法,例如 FirstOrDefault 或 Where 。
動態跨應用程式域欄位存取
OpCodes.Ldflda如果包含您嘗試擷取其位址的欄位的物件不在程式碼執行所在的應用程式域中,則 Microsoft 中繼語言 (MSIL) 指令會擲回 InvalidOperationException 例外狀況。 欄位的位址只能從它所在的應用程式域存取。
擲回 InvalidOperationException 例外狀況
只有在因為某些原因而不支援特定方法呼叫的物件狀態時,才應該擲回 InvalidOperationException 例外狀況。 也就是說,在某些情況下或內容中方法呼叫有效,但在其他情況下則無效。
如果方法調用失敗是因為不正確引數所造成,則 ArgumentException 應該改為擲回其其中一個衍生類別 ArgumentNullException 或 ArgumentOutOfRangeException 。
其他資訊
InvalidOperationException 會使用 HRESULT COR_E_INVALIDOPERATION,其值為 0x80131509。
如需執行個體的初始屬性值的清單InvalidOperationException,請參閱InvalidOperationException建構函式。
建構函式
InvalidOperationException() |
初始化 InvalidOperationException 類別的新執行個體。 |
InvalidOperationException(SerializationInfo, StreamingContext) |
使用序列化資料,初始化 InvalidOperationException 類別的新執行個體。 |
InvalidOperationException(String) |
使用指定的錯誤訊息,初始化 InvalidOperationException 類別的新執行個體。 |
InvalidOperationException(String, Exception) |
使用指定的錯誤訊息以及造成此例外狀況的內部例外狀況的參考,初始化 InvalidOperationException 類別的新執行個體。 |
屬性
Data |
取得鍵值組的集合,這些鍵值組會提供關於例外狀況的其他使用者定義資訊。 (繼承來源 Exception) |
HelpLink |
取得或設定與這個例外狀況相關聯的說明檔連結。 (繼承來源 Exception) |
HResult |
取得或設定 HRESULT,它是指派給特定例外狀況的編碼數值。 (繼承來源 Exception) |
InnerException |
取得造成目前例外狀況的 Exception 執行個體。 (繼承來源 Exception) |
Message |
取得描述目前例外狀況的訊息。 (繼承來源 Exception) |
Source |
取得或設定造成錯誤的應用程式或物件的名稱。 (繼承來源 Exception) |
StackTrace |
取得呼叫堆疊上即時運算框架的字串表示。 (繼承來源 Exception) |
TargetSite |
取得擲回目前例外狀況的方法。 (繼承來源 Exception) |
方法
Equals(Object) |
判斷指定的物件是否等於目前的物件。 (繼承來源 Object) |
GetBaseException() |
在衍生類別中覆寫時,傳回一或多個後續的例外狀況的根本原因 Exception。 (繼承來源 Exception) |
GetHashCode() |
做為預設雜湊函式。 (繼承來源 Object) |
GetObjectData(SerializationInfo, StreamingContext) |
在衍生類別中覆寫時,使用例外狀況的資訊設定 SerializationInfo。 (繼承來源 Exception) |
GetType() |
取得目前執行個體的執行階段類型。 (繼承來源 Exception) |
MemberwiseClone() |
建立目前 Object 的淺層複製。 (繼承來源 Object) |
ToString() |
建立並傳回目前例外狀況的字串表示。 (繼承來源 Exception) |
事件
SerializeObjectState |
已過時。
當例外狀況序列化,以建立包含例外狀況相關序列化資料的例外狀況狀態物件時,就會發生此事件。 (繼承來源 Exception) |