InvalidOperationException 类

定义

当方法调用对于对象的当前状态无效时引发的异常。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
继承
InvalidOperationException
派生
属性

注解

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:

重要

由于在各种情况下可能会引发Message 异常,因此请务必阅读属性返回的异常消息。InvalidOperationExceptionBecause 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 的> nullT转换为其基础类型< Casting a Nullable<T> that is null to its underlying type
对空集合调用 system.exception 方法Calling a System.Linq.Enumerable method on an empty collection
对没有一个元素的序列调用 SingleOrDefault 或可枚举的。Calling 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 的 GUI (图形用户界面) 应用程序框架 (如 Windows 窗体和 Windows Presentation Foundation (WPF)) 只允许从创建和管理 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). 当你尝试从 ui 线程之外的其他线程访问 ui 元素时,将引发。InvalidOperationExceptionAn 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 marshaled 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, check the CoreDispatcher.HasThreadAccess property 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.

  • 在 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:

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

  • 名为threadExampleBtn的按钮控件。A 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

Visual Basic foreach中的C#语句For Each或语句中的语句用于循环访问集合的成员, 并读取或修改其各个元素。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语句foreach而不是或For Each来循环访问元素。If 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()方法的调用将InvalidOperationException引发。As 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>.CompareTo CompareTo或方法。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<的可为 null 的 T > 强制转换为其基础类型Casting a Nullable<T> that is null to its underlying type

如果尝试强制转换Nullable<T>InvalidOperationException其基础null类型的值, 则会引发异常并显示错误消息 "可以为 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.exception 方法Calling a System.Linq.Enumerable method on an empty collection

Enumerable.AggregateEnumerable.Average、 、Enumerable.Max、、 、和Enumerable.SingleOrDefault方法对序列执行操作并返回单个结果。 Enumerable.Min Enumerable.First Enumerable.Last Enumerable.SingleThe 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重载返回null, 则这些方法的某些重载会引发异常。Some 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对于引用类型, 默认值为 0; 对于数值数据类型DateTime.MinValue , 默认值为零; DateTime对于类型, 则为。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.

对没有一个元素的序列调用 SingleOrDefault 或可枚举的。Calling 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方法, FirstOrDefault例如或WhereOtherwise, 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包含您尝试检索其地址的字段所在InvalidOperationException的对象不在执行您的代码的应用程序域中, 则 Microsoft 中间语言 (MSIL) 指令会引发异常。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使用 COR_E_INVALIDOPERATION 值为0x80131509 的 HRESULT。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 类的新实例。Initializes a new instance of the InvalidOperationException class.

InvalidOperationException(SerializationInfo, StreamingContext)

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

InvalidOperationException(String)

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

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

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

(继承自 Exception)
HelpLink

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

(继承自 Exception)
HResult

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

(继承自 Exception)
InnerException

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

(继承自 Exception)
Message

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

(继承自 Exception)
Source

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

(继承自 Exception)
StackTrace

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

(继承自 Exception)
TargetSite

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

(继承自 Exception)

方法

Equals(Object)

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

(继承自 Object)
GetBaseException()

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

(继承自 Exception)
GetHashCode()

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

(继承自 Object)
GetObjectData(SerializationInfo, StreamingContext)

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

(继承自 Exception)
GetType()

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

(继承自 Exception)
MemberwiseClone()

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

(继承自 Object)
ToString()

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

(继承自 Exception)

事件

SerializeObjectState

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

(继承自 Exception)

适用于

另请参阅