InvalidOperationException InvalidOperationException InvalidOperationException InvalidOperationException Class

定义

当方法调用对于对象的当前状态无效时引发的异常。The exception that is thrown when a method call is invalid for the object's current state.

public ref class InvalidOperationException : SystemException
[System.Runtime.InteropServices.ComVisible(true)]
[System.Serializable]
public class InvalidOperationException : SystemException
type InvalidOperationException = class
    inherit SystemException
Public Class InvalidOperationException
Inherits SystemException
继承
InvalidOperationExceptionInvalidOperationExceptionInvalidOperationExceptionInvalidOperationException
派生
属性

注解

InvalidOperationException 可在情况下无法调用的方法是由无效参数以外的原因。InvalidOperationException is used in cases when the failure to invoke a method is caused by reasons other than invalid arguments. 通常情况下,它会引发一个对象的状态不能支持方法调用。Typically, it is thrown when the state of an object cannot support the method call. 例如,InvalidOperationException如由方法引发异常:For example, an InvalidOperationException exception is thrown by methods such as:

重要

因为InvalidOperationException可能会引发异常在各种情况下,务必要读取返回的异常消息Message属性。Because the InvalidOperationException exception can be thrown in a wide variety of circumstances, it is important to read the exception message returned by the Message property.

本节内容:In this section:

InvalidOperationException 异常的一些常见原因 Some common causes of InvalidOperationException exceptions
正在更新从非 UI 线程的 UI 线程Updating a UI thread from a non-UI thread
更改循环访问它时收集Changing a collection while iterating it
无法比较的对象数组或集合排序Sorting an array or collection whose objects cannot be compared
转换一个可以为 Null<T> null 为其基础类型 Casting a Nullable<T> that is null to its underlying type
对空集合调用了 System.Linq.Enumerable 方法Calling a System.Linq.Enumerable method on an empty collection
对不带一个元素序列调用后,Enumerable.Single 或 Enumerable.SingleOrDefaultCalling Enumerable.Single or Enumerable.SingleOrDefault on a sequence without one element
动态跨应用程序域字段访问Dynamic cross-application domain field access
引发 InvalidOperationException 异常Throwing an InvalidOperationException exception
杂项信息Miscellaneous information

InvalidOperationException 异常的一些常见原因Some common causes of InvalidOperationException exceptions

以下部分介绍了一些常见顺序中的情况下InvalidOperationException应用程序中引发异常。The following sections show how some common cases in which in InvalidOperationException exception is thrown in an app. 如何处理问题取决于具体情况。How you handle the issue depends on the specific situation. 大多数情况下,但是,异常会从开发人员错误和InvalidOperationException可以预料并避免异常。Most commonly, however, the exception results from developer error, and the InvalidOperationException exception can be anticipated and avoided.

正在更新从非 UI 线程的 UI 线程Updating a UI thread from a non-UI thread

通常情况下,工作线程用于执行涉及收集数据以在应用程序的用户界面中显示某些后台工作。Often, worker threads are used to perform some background work that involves gathering data to be displayed in an application's user interface. 但是。However. .NET Framework 中,例如 Windows 窗体和 Windows Presentation Foundation (WPF) 的大多数 GUI (图形用户界面) 应用程序框架,你只能从线程创建和管理 UI (主数据连接或 UI 线程) 访问 GUI 对象。most GUI (graphical user interface) application frameworks for the .NET Framework, such as Windows Forms and Windows Presentation Foundation (WPF), let you access GUI objects only from the thread that creates and manages the UI (the Main or UI thread). InvalidOperationException尝试从 UI 线程以外的线程访问 UI 元素时引发。An InvalidOperationException is thrown when you try to access a UI element from a thread other than the UI thread. 下表中显示异常消息的文本。The text of the exception message is shown in the following table.

应用程序类型Application Type 消息Message
WPF 应用程序WPF app 调用线程无法访问此对象,因为另一个线程拥有它。The calling thread cannot access this object because a different thread owns it.
UWP 应用UWP app 应用程序为另一个线程调用已封送的界面。The application called an interface that was marshalled for a different thread.
Windows 窗体应用Windows Forms app 跨线程操作无效:它已创建控件 TextBox1 从线程以外的线程访问。Cross-thread operation not valid: Control 'TextBox1' accessed from a thread other than the thread it was created on.

.NET Framework 的 UI 框架实现调度程序模式,其中包含用于检查是否正在 UI 线程上执行对 UI 元素的成员的调用的方法和其他用以计划在 UI 线程上的调用方法:UI frameworks for the .NET Framework implement a dispatcher pattern that includes a method to check whether a call to a member of a UI element is being executed on the UI thread, and other methods to schedule the call on the UI thread:

  • 在 WPF 应用中,调用Dispatcher.CheckAccess方法,以确定方法是否正在非 UI 线程上运行。In WPF apps, call the Dispatcher.CheckAccess method to determine if a method is running on a non-UI thread. 它将返回true方法是否在 UI 线程上运行和false否则为。It returns true if the method is running on the UI thread and false otherwise. 调用的重载之一Dispatcher.Invoke方法来计划在 UI 线程上的调用。Call one of the overloads of the Dispatcher.Invoke method to schedule the call on the UI thread.

  • 在 UWP 应用中调用CoreDispatcher.HasThreadAccess方法,以确定方法是否正在非 UI 线程上运行。In UWP apps, call the CoreDispatcher.HasThreadAccess method to determine if a method is running on a non-UI thread. 调用CoreDispatcher.RunAsync要执行更新 UI 线程的委托的方法。Call the CoreDispatcher.RunAsync method to execute a delegate that updates the UI thread. 使用Use the

  • 在 Windows 窗体应用程序使用Control.InvokeRequired属性来确定方法是否正在非 UI 线程上运行。In Windows Forms apps, use the Control.InvokeRequired property to determine if a method is running on a non-UI thread. 调用的重载之一Control.Invoke要执行更新 UI 线程的委托的方法。Call one of the overloads of the Control.Invoke method to execute a delegate that updates the UI thread.

以下示例说明了InvalidOperationException当你尝试更新从创建它的线程以外的线程的 UI 元素时引发的异常。The following examples illustrate the InvalidOperationException exception that is thrown when you attempt to update a UI element from a thread other than the thread that created it. 每个示例需要创建两个控件:Each example requires that you create two controls:

  • 名为的文本框控件textBox1A text box control named textBox1. 在 Windows 窗体应用中,应设置其Multiline属性设置为trueIn a Windows Forms app, you should set its Multiline property to true.

  • 名为的按钮控件threadExampleBtnA button control named threadExampleBtn. 本示例提供了一个处理程序ThreadsExampleBtn_Click,为按钮的Click事件。The example provides a handler, ThreadsExampleBtn_Click, for the button's Click event.

每种情况下,threadExampleBtn_Click事件处理程序调用DoSomeWork方法两次。In each case, the threadExampleBtn_Click event handler calls the DoSomeWork method twice. 第一次调用以同步方式运行并成功。The first call runs synchronously and succeeds. 但第二次调用,因为它以异步方式运行,线程池线程上尝试中非 UI 线程更新 UI。But the second call, because it runs asynchronously on a thread pool thread, attempts to update the UI from a non-UI thread. 这会导致InvalidOperationException异常。This results in a InvalidOperationException exception.

WPF 和 UWP 应用WPF and UWP apps

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 应用程序中的异常。The following version of the DoSomeWork method eliminates the exception in a WPF app.

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 应用中的异常。The following version of the DoSomeWork method eliminates the exception in a 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 窗体应用Windows Forms apps

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 窗体应用程序中的异常。The following version of the DoSomeWork method eliminates the exception in a Windows Forms app.

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

更改循环访问它时收集Changing a collection while iterating it

foreach C# 中的语句或For Each在 Visual Basic 中的语句用于循环访问集合的成员和读取或修改它的各个元素。The foreach statement in C# or For Each statement in Visual Basic is used to iterate the members of a collection and to read or modify its individual elements. 但是,它不能用于添加或从集合中移除项。However, it can't be used to add or remove items from the collection. 这样做将引发InvalidOperationException异常并显示消息,类似于,"修改集合;可能无法执行枚举操作。"Doing this throws an InvalidOperationException exception with a message that is similar to, "Collection was modified; enumeration operation may not execute."

下面的示例循环访问一系列整数尝试添加到集合的每个整数的平方。The following example iterates a collection of integers attempts to add the square of each integer to the collection. 本示例将引发InvalidOperationException与首次调用List<T>.Add方法。The example throws an InvalidOperationException with the first call to the List<T>.Add method.

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()
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()

具体取决于你的应用程序逻辑,可以消除两种方式之一中的异常:You can eliminate the exception in one of two ways, depending on your application logic:

  • 如果必须将元素添加到集合中循环访问它时,就可以通过索引使用迭代它for语句而不是foreachFor EachIf elements must be added to the collection while iterating it, you can iterate it by index using the for statement instead of foreach or For Each. 下面的示例使用 for 语句添加到集合的集合中的数字的平方。The following example uses the for statement to add the square of numbers in the collection to the collection.

    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
    
    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,或该示例一样,通过将分配数中的元素的数组变量以及使用它来建立循环的上限。Note that you must establish the number of iterations before iterating the collection either by using a counter inside the loop that will exit the loop appropriately, by iterating backward, from Count - 1 to 0, or, as the example does, by assigning the number of elements in the array to a variable and using it to establish the upper bound of the loop. 否则,如果元素添加到每次迭代集合,会导致无限循环。Otherwise, if an element is added to the collection on every iteration, an endless loop results.

  • 如果不需要将元素添加到集合中循环访问它时,您可以存储临时集合中添加循环访问集合来完成时要添加的元素。If it is not necessary to add elements to the collection while iterating it, you can store the elements to be added in a temporary collection that you add when iterating the collection has finished. 下面的示例使用此方法添加到一个临时的集合,集合中的数字的平方然后将组合到单个数组对象的集合。The following example uses this approach to add the square of numbers in a collection to a temporary collection, and then to combine the collections into a single array object.

    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
    
    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
    

无法比较的对象数组或集合排序Sorting an array or collection whose objects cannot be compared

通用排序方法,如Array.Sort(Array)方法或List<T>.Sort()方法,通常需要至少一个要排序的对象实现IComparable<T>IComparable接口。General-purpose sorting methods, such as the Array.Sort(Array) method or the List<T>.Sort() method, usually require that at least one of the objects to be sorted implement the IComparable<T> or the IComparable interface. 如果不是,不能排序集合或数组,并且该方法将引发InvalidOperationException异常。If not, the collection or array cannot be sorted, and the method throws an InvalidOperationException exception. 下面的示例定义Person类存储两个Person对象在泛型List<T>对象,并尝试对其进行排序。The following example defines a Person class, stores two Person objects in a generic List<T> object, and attempts to sort them. 如示例所示,对的调用中的输出List<T>.Sort()方法会抛出InvalidOperationExceptionAs the output from the example shows, the call to the List<T>.Sort() method throws an 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()
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()

您可以消除在三种方式中的异常:You can eliminate the exception in any of three ways:

  • 如果你可以拥有想要进行排序 (即,如果您控制其源代码) 的类型,你可以修改它以实现IComparable<T>IComparable接口。If you can own the type that you are trying to sort (that is, if you control its source code), you can modify it to implement the IComparable<T> or the IComparable interface. 这要求您实现任一IComparable<T>.CompareToCompareTo方法。This requires that you implement either the IComparable<T>.CompareTo or the CompareTo method. 向现有类型添加的接口实现不是一项重大更改。Adding an interface implementation to an existing type is not a breaking change.

    下面的示例使用此方法提供IComparable<T>实现Person类。The following example uses this approach to provide an IComparable<T> implementation for the Person class. 您仍然可以调用集合或数组的常规排序方法,并如示例输出所示,成功排序集合。You can still call the collection or array's general sorting method and, as the output from the example shows, the collection sorts successfully.

    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}", LastName, 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
    
    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}", LastName, 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>接口。If you cannot modify the source code for the type you are trying to sort, you can define a special-purpose sorting class that implements the IComparer<T> interface. 您可以调用的重载Sort方法,包括IComparer<T>参数。You can call an overload of the Sort method that includes an IComparer<T> parameter. 这种方法是特别有用,如果你想要开发专用的排序类,可以对基于多个条件的对象进行排序。This approach is especially useful if you want to develop a specialized sorting class that can sort objects based on multiple criteria.

    下面的示例使用通过开发自定义方法PersonComparer类,用于排序Person集合。The following example uses the approach by developing a custom PersonComparer class that is used to sort Person collections. 然后将传递到此类的实例List<T>.Sort(IComparer<T>)方法。It then passes an instance of this class to the List<T>.Sort(IComparer<T>) method.

    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
    
    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>要执行的排序委托。If you cannot modify the source code for the type you are trying to sort, you can create a Comparison<T> delegate to perform the sorting. 委托签名The delegate signature is

    Function Comparison(Of T)(x As T, y As T) As Integer  
    
    int Comparison<T>(T x, T y)  
    

    下面的示例使用通过定义方法PersonComparison匹配的方法Comparison<T>委托签名。The following example uses the approach by defining a PersonComparison method that matches the Comparison<T> delegate signature. 然后将传递到此委托List<T>.Sort(Comparison<T>)方法。It then passes this delegate to the List<T>.Sort(Comparison<T>) method.

    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
    
    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 > 这是为其基础类型为 nullCasting a Nullable<T> that is null to its underlying type

尝试进行强制转换Nullable<T>值,该值是null为其基础类型将引发InvalidOperationException异常并显示错误消息"可以为 Null 的对象必须具有一个值。Attempting to cast a Nullable<T> value that is null to its underlying type throws an InvalidOperationException exception and displays the error message, "Nullable object must have a value.

下面的示例将引发InvalidOperationException它将尝试来循环访问数组时出现异常,包括Nullable(Of Integer)值。The following example throws an InvalidOperationException exception when it attempts to iterate an array that includes a Nullable(Of Integer) value.

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()
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()

若要避免此异常:To prevent the exception:

下面的示例可同时做到这以避免InvalidOperationException异常。The following example does both to avoid the InvalidOperationException exception.

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
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 方法Calling a System.Linq.Enumerable method on an empty collection

Enumerable.AggregateEnumerable.AverageEnumerable.FirstEnumerable.LastEnumerable.MaxEnumerable.MinEnumerable.Single,和Enumerable.SingleOrDefault方法对序列执行操作并返回单个结果。The Enumerable.Aggregate, Enumerable.Average, Enumerable.First, Enumerable.Last, Enumerable.Max, Enumerable.Min, Enumerable.Single, and Enumerable.SingleOrDefault methods perform operations on a sequence and return a single result. 这些方法的一些重载会引发InvalidOperationException异常时该序列为空,而其他重载返回nullSome overloads of these methods throw an InvalidOperationException exception when the sequence is empty, while other overloads return null. Enumerable.SingleOrDefault方法还会引发InvalidOperationException序列包含多个元素时出现异常。The Enumerable.SingleOrDefault method also throws an InvalidOperationException exception when the sequence contains more than one element.

备注

引发方法的大多数InvalidOperationException异常是重载。Most of the methods that throw an InvalidOperationException exception are overloads. 请确保您了解您选择的重载的行为。Be sure that you understand the behavior of the overload that you choose.

下表列出了从异常消息InvalidOperationException调用一些由引发的异常对象System.Linq.Enumerable方法。The following table lists the exception messages from the InvalidOperationException exception objects thrown by calls to some System.Linq.Enumerable methods.

方法Method 消息Message
Aggregate
Average
Last
Max
Min
序列不包含任何元素Sequence contains no elements
First 序列不包含任何匹配元素Sequence contains no matching element
Single
SingleOrDefault
序列包含多个匹配元素Sequence contains more than one matching element

消除或处理异常的方式取决于应用程序的假设以及所调用的特定方法。How you eliminate or handle the exception depends on your application's assumptions and on the particular method you call.

示例提供了更多详细信息。The examples provide additional detail.

下面的示例使用Enumerable.Average方法来计算其值是大于 4 序列的平均值。The following example uses the Enumerable.Average method to compute the average of a sequence whose values are greater than 4. 由于原始数组中的任何值超过 4、 任何值都包含在序列中,并且该方法将引发InvalidOperationException异常。Since no values from the original array exceed 4, no values are included in the sequence, and the method throws an InvalidOperationException exception.

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()
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方法,以确定是否序列不包含任何元素之前调用的方法处理的序列,如以下示例所示。The exception can be eliminated by calling the Any method to determine whether the sequence contains any elements before calling the method that processes the sequence, as the following example shows.

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.
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方法返回一个序列或在序列中满足指定的条件的第一个元素中的第一项。The Enumerable.First method returns the first item in a sequence or the first element in a sequence that satisfies a specified condition. 如果序列为空,因此不会将第一个元素,则会引发InvalidOperationException异常。If the sequence is empty and therefore does not have a first element, it throws an InvalidOperationException exception.

在以下示例中,Enumerable.First<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>)方法会抛出InvalidOperationException异常因为 dbQueryResults 数组不包含大于 4 的元素。In the following example, the Enumerable.First<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>) method throws an InvalidOperationException exception because the dbQueryResults array doesn't contain an element greater than 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()
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以返回特定值或默认值。You can call the Enumerable.FirstOrDefault method instead of Enumerable.First to return a specified or default value. 如果该方法不会查找序列中的第一个元素,则返回该数据类型的默认值。If the method does not find a first element in the sequence, it returns the default value for that data type. 默认值是null引用类型,为零的数值数据类型,并DateTime.MinValueDateTime类型。The default value is null for a reference type, zero for a numeric data type, and DateTime.MinValue for the DateTime type.

备注

解释返回的值Enumerable.FirstOrDefault方法通常很复杂的类型的默认值可以是有效的值序列中的事实。Interpreting the value returned by the Enumerable.FirstOrDefault method is often complicated by the fact that the default value of the type can be a valid value in the sequence. 在此情况下,您调用Enumerable.Any方法,以确定序列是否具有有效的成员,然后才能调用Enumerable.First方法。In this case, you an call the Enumerable.Any method to determine whether the sequence has valid members before calling the Enumerable.First method.

下面的示例调用Enumerable.FirstOrDefault<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>)方法,以阻止InvalidOperationException上一示例中引发异常。The following example calls the Enumerable.FirstOrDefault<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>) method to prevent the InvalidOperationException exception thrown in the previous example.

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.
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.SingleOrDefaultCalling Enumerable.Single or Enumerable.SingleOrDefault on a sequence without one element

Enumerable.Single方法将返回一个序列的唯一元素或满足指定的条件的序列的唯一元素。The Enumerable.Single method returns the only element of a sequence, or the only element of a sequence that meets a specified condition. 如果在序列中,没有任何元素,或如果不存在多个元素,该方法将引发InvalidOperationException异常。If there are no elements in the sequence, or if there is more than one element , the method throws an InvalidOperationException exception.

可以使用Enumerable.SingleOrDefault方法以返回默认值而不是序列中不包含任何元素时引发异常。You can use the Enumerable.SingleOrDefault method to return a default value instead of throwing an exception when the sequence contains no elements. 但是,Enumerable.SingleOrDefault方法仍将引发InvalidOperationException序列包含多个元素时出现异常。However, the Enumerable.SingleOrDefault method still throws an InvalidOperationException exception when the sequence contains more than one element.

下表列出了从异常消息InvalidOperationException通过调用引发的异常对象Enumerable.SingleEnumerable.SingleOrDefault方法。The following table lists the exception messages from the InvalidOperationException exception objects thrown by calls to the Enumerable.Single and Enumerable.SingleOrDefault methods.

方法Method 消息Message
Single 序列不包含任何匹配元素Sequence contains no matching element
Single
SingleOrDefault
序列包含多个匹配元素Sequence contains more than one matching element

在下面的示例中,调用Enumerable.Single方法会抛出InvalidOperationException异常因为序列没有大于 4 的元素。In the following example, the call to the Enumerable.Single method throws an InvalidOperationException exception because the sequence doesn't have an element greater than 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()
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方法。The following example attempts to prevent the InvalidOperationException exception thrown when a sequence is empty by instead calling the Enumerable.SingleOrDefault method. 但是,因为此序列返回其值大于 2 的多个元素,它还会引发InvalidOperationException异常。However, because this sequence returns multiple elements whose value is greater than 2, it also throws an InvalidOperationException exception.

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()
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方法假定序列或满足指定的条件的序列包含仅有一个元素。Calling the Enumerable.Single method assumes that either a sequence or the sequence that meets specified criteria contains only one element. Enumerable.SingleOrDefault 假定具有零个或一个结果,但没有更多的序列。Enumerable.SingleOrDefault assumes a sequence with zero or one result, but no more. 如果这种假设是一个故意安排对您来说并不满足这些条件,重新引发或捕捉生成InvalidOperationException适用。If this assumption is a deliberate one on your part and these conditions are not met, rethrowing or catching the resulting InvalidOperationException is appropriate. 否则为或者如果希望无效的条件将以某种频率发生,则应考虑使用其他一些Enumerable方法,如FirstOrDefaultWhereOtherwise, or if you expect that invalid conditions will occur with some frequency, you should consider using some other Enumerable method, such as FirstOrDefault or Where.

动态跨应用程序域字段访问Dynamic cross-application domain field access

OpCodes.Ldflda Microsoft 中间语言 (MSIL) 指令将引发InvalidOperationException异常的对象是否包含要检索其地址的字段不在其中执行你的代码在应用程序域中。The OpCodes.Ldflda Microsoft intermediate language (MSIL) instruction throws an InvalidOperationException exception if the object containing the field whose address you are trying to retrieve is not within the application domain in which your code is executing. 只能从它所在的应用程序域访问字段的地址。The address of a field can only be accessed from the application domain in which it resides.

引发 InvalidOperationException 异常Throwing an InvalidOperationException exception

应引发InvalidOperationException仅出于某种原因您对象的状态不支持的特定方法调用时出现异常。You should throw an InvalidOperationException exception only when the state of your object for some reason does not support a particular method call. 它是方法调用是在某些情况下或上下文中有效但在其他无效。That is, the method call is valid in some circumstances or contexts, but is invalid in others.

如果方法调用失败是由于参数无效,则ArgumentException或其派生类之一ArgumentNullExceptionArgumentOutOfRangeException,应改为引发。If the method invocation failure is due to invalid arguments, then ArgumentException or one of its derived classes, ArgumentNullException or ArgumentOutOfRangeException, should be thrown instead.

杂项信息Miscellaneous information

InvalidOperationException 使用 HRESULT 并返回 COR_E_INVALIDOPERATION,其值 0x80131509。InvalidOperationException uses the HRESULT COR_E_INVALIDOPERATION, which has the value 0x80131509.

有关实例的初始属性值的列表InvalidOperationException,请参阅InvalidOperationException构造函数。For a list of initial property values for an instance of InvalidOperationException, see the InvalidOperationException constructors.

构造函数

InvalidOperationException() InvalidOperationException() InvalidOperationException() InvalidOperationException()

初始化 InvalidOperationException 类的新实例。Initializes a new instance of the InvalidOperationException class.

InvalidOperationException(SerializationInfo, StreamingContext) InvalidOperationException(SerializationInfo, StreamingContext) InvalidOperationException(SerializationInfo, StreamingContext) InvalidOperationException(SerializationInfo, StreamingContext)

用序列化数据初始化 InvalidOperationException 类的新实例。Initializes a new instance of the InvalidOperationException class with serialized data.

InvalidOperationException(String) InvalidOperationException(String) InvalidOperationException(String) InvalidOperationException(String)

用指定的错误消息初始化 InvalidOperationException 类的新实例。Initializes a new instance of the InvalidOperationException class with a specified error message.

InvalidOperationException(String, Exception) InvalidOperationException(String, Exception) InvalidOperationException(String, Exception) InvalidOperationException(String, Exception)

使用指定的错误消息和对作为此异常原因的内部异常的引用来初始化 InvalidOperationException 类的新实例。Initializes a new instance of the InvalidOperationException class with a specified error message and a reference to the inner exception that is the cause of this exception.

属性

Data Data Data Data

获取提供有关异常的其他用户定义信息的键/值对集合。Gets a collection of key/value pairs that provide additional user-defined information about the exception.

(Inherited from Exception)
HelpLink HelpLink HelpLink HelpLink

获取或设置指向与此异常关联的帮助文件链接。Gets or sets a link to the help file associated with this exception.

(Inherited from Exception)
HResult HResult HResult HResult

获取或设置 HRESULT(一个分配给特定异常的编码数字值)。Gets or sets HRESULT, a coded numerical value that is assigned to a specific exception.

(Inherited from Exception)
InnerException InnerException InnerException InnerException

获取导致当前异常的 Exception 实例。Gets the Exception instance that caused the current exception.

(Inherited from Exception)
Message Message Message Message

获取描述当前异常的消息。Gets a message that describes the current exception.

(Inherited from Exception)
Source Source Source Source

获取或设置导致错误的应用程序或对象的名称。Gets or sets the name of the application or the object that causes the error.

(Inherited from Exception)
StackTrace StackTrace StackTrace StackTrace

获取调用堆栈上的即时框架字符串表示形式。Gets a string representation of the immediate frames on the call stack.

(Inherited from Exception)
TargetSite TargetSite TargetSite TargetSite

获取引发当前异常的方法。Gets the method that throws the current exception.

(Inherited from Exception)

方法

Equals(Object) Equals(Object) Equals(Object) Equals(Object)

确定指定的对象是否等于当前对象。Determines whether the specified object is equal to the current object.

(Inherited from Object)
GetBaseException() GetBaseException() GetBaseException() GetBaseException()

当在派生类中重写时,返回 Exception,它是一个或多个并发的异常的根源。When overridden in a derived class, returns the Exception that is the root cause of one or more subsequent exceptions.

(Inherited from Exception)
GetHashCode() GetHashCode() GetHashCode() GetHashCode()

作为默认哈希函数。Serves as the default hash function.

(Inherited from Object)
GetObjectData(SerializationInfo, StreamingContext) GetObjectData(SerializationInfo, StreamingContext) GetObjectData(SerializationInfo, StreamingContext) GetObjectData(SerializationInfo, StreamingContext)

当在派生类中重写时,用关于异常的信息设置 SerializationInfoWhen overridden in a derived class, sets the SerializationInfo with information about the exception.

(Inherited from Exception)
GetType() GetType() GetType() GetType()

获取当前实例的运行时类型。Gets the runtime type of the current instance.

(Inherited from Exception)
MemberwiseClone() MemberwiseClone() MemberwiseClone() MemberwiseClone()

创建当前 Object 的浅表副本。Creates a shallow copy of the current Object.

(Inherited from Object)
ToString() ToString() ToString() ToString()

创建并返回当前异常的字符串表示形式。Creates and returns a string representation of the current exception.

(Inherited from Exception)

事件

SerializeObjectState SerializeObjectState SerializeObjectState SerializeObjectState

当异常被序列化用来创建包含有关该异常的徐列出数据的异常状态对象时会出现该问题。Occurs when an exception is serialized to create an exception state object that contains serialized data about the exception.

(Inherited from Exception)

适用于

另请参阅