InvalidOperationException 類別

定義

當方法呼叫對物件的目前狀態無效時所擲回的例外狀況。

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
衍生
屬性

備註

InvalidOperationException 當叫用方法的失敗是由無效引數以外的原因所造成時使用。 一般而言,當物件的狀態無法支援方法呼叫時,就會擲回它。 例如, InvalidOperationException 下列方法會擲回例外狀況:

重要

InvalidOperationException因為例外狀況可以在各種不同的情況下擲回,所以請務必讀取 屬性傳回的 Message 例外狀況訊息。

本節內容:

InvalidOperationException 例外狀況的一些常見原因
從非 UI 執行緒更新 UI 執行緒
在反覆運算集合時變更集合
排序無法比較物件的陣列或集合
將 NullableT < > 轉換成其基礎類型
在空集合上呼叫 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 應用程式中,檢查 CoreDispatcher.HasThreadAccess 屬性,以判斷方法是否在非 UI 執行緒上執行。 CoreDispatcher.RunAsync呼叫 方法來執行更新 UI 執行緒的委派。

  • 在 Windows Forms 應用程式中,使用 Control.InvokeRequired 屬性來判斷方法是否在非 UI 執行緒上執行。 呼叫 方法的 Control.Invoke 其中一個多載,以執行更新 UI 執行緒的委派。

下列範例說明 InvalidOperationException 當您嘗試從建立它之執行緒以外的執行緒更新 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 應用程式中的例外狀況。

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

在反覆運算集合時變更集合

foreachC# 中的 語句、 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 ,而不是 foreachfor...inFor Eachfor 逐一查看它。 下列範例會使用 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 擲回例外狀況。 下列範例會定義類別、將兩 PersonPerson 物件儲存在泛型 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 的轉換為其基礎型別的 Null <T>

嘗試轉換 Nullable<T> 其基礎類型的值 nullInvalidOperationException 擲回例外狀況,並顯示錯誤訊息:「可為 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()

若要防止例外狀況:

下列範例會執行這兩個動作來避免例外狀況 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.AggregateEnumerable.AverageEnumerable.FirstEnumerable.LastEnumerable.Max Enumerable.Min 、、 Enumerable.SingleEnumerable.SingleOrDefault 方法會在序列上執行作業,並傳回單一結果。 當序列是空的時,這些方法的某些多載會擲 InvalidOperationException 回例外狀況,而其他多載則會傳回 null 。 當序列包含一個以上的專案時,方法 Enumerable.SingleOrDefault 也會擲回 InvalidOperationException 例外狀況。

注意

大部分擲回 InvalidOperationException 例外狀況的方法都是多載。 請確定您瞭解您選擇的多載行為。

下表列出呼叫某些 System.Linq.Enumerable 方法所擲回之例外狀況物件中的 InvalidOperationException 例外狀況訊息。

方法 訊息
Aggregate
Average
Last
Max
Min
序列不包含任何元素
First 序列未包含相符的專案
Single
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.SingleEnumerable.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 方法,例如 FirstOrDefaultWhere

動態跨應用程式域欄位存取

OpCodes.Ldflda如果包含您嘗試擷取其位址的欄位的物件不在程式碼執行所在的應用程式域中,則 Microsoft 中繼語言 (MSIL) 指令會擲回 InvalidOperationException 例外狀況。 欄位的位址只能從它所在的應用程式域存取。

擲回 InvalidOperationException 例外狀況

只有在因為某些原因而不支援特定方法呼叫的物件狀態時,才應該擲回 InvalidOperationException 例外狀況。 也就是說,在某些情況下或內容中方法呼叫有效,但在其他情況下則無效。

如果方法調用失敗是因為不正確引數所造成,則 ArgumentException 應該改為擲回其其中一個衍生類別 ArgumentNullExceptionArgumentOutOfRangeException

其他資訊

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)

適用於

另請參閱