Delen via


System.InvalidOperationException-klasse

In dit artikel vindt u aanvullende opmerkingen in de referentiedocumentatie voor deze API.

InvalidOperationException wordt gebruikt in gevallen waarin het niet aanroepen van een methode wordt veroorzaakt door andere redenen dan ongeldige argumenten. Normaal gesproken wordt deze gegenereerd wanneer de status van een object de methodeaanroep niet kan ondersteunen. Een uitzondering wordt bijvoorbeeld InvalidOperationException gegenereerd door methoden zoals:

  • IEnumerator.MoveNext als objecten van een verzameling worden gewijzigd nadat de enumerator is gemaakt. Zie Een verzameling wijzigen tijdens het herhalen voor meer informatie.
  • ResourceSet.GetString als de resourceset wordt gesloten voordat de methode-aanroep wordt uitgevoerd.
  • XContainer.Addals het object of de objecten die moeten worden toegevoegd, resulteert in een onjuist gestructureerd XML-document.
  • Een methode die probeert de gebruikersinterface te bewerken vanuit een thread die niet de hoofd- of UI-thread is.

Belangrijk

Omdat de InvalidOperationException uitzondering in een groot aantal omstandigheden kan worden gegenereerd, is het belangrijk om het uitzonderingsbericht te lezen dat door de Message eigenschap wordt geretourneerd.

InvalidOperationException maakt gebruik van HRESULT COR_E_INVALIDOPERATION, met de waarde 0x80131509.

Zie de InvalidOperationException constructors voor een lijst met initiële eigenschapswaarden voor een exemplaar vanInvalidOperationException.

Veelvoorkomende oorzaken van InvalidOperationException-uitzonderingen

In de volgende secties ziet u hoe enkele veelvoorkomende gevallen waarin een InvalidOperationException uitzondering optreedt in een app. Hoe u het probleem afhandelt, is afhankelijk van de specifieke situatie. De uitzondering wordt meestal echter veroorzaakt door een fout in de ontwikkelaar en de InvalidOperationException uitzondering kan worden verwacht en vermeden.

Een UI-thread bijwerken vanuit een niet-UI-thread

Werkrolthreads worden vaak gebruikt om achtergrondwerk uit te voeren waarbij gegevens moeten worden verzameld die moeten worden weergegeven in de gebruikersinterface van een toepassing. Echter. De meeste GUI-toepassingsframeworks (grafische gebruikersinterface) voor .NET, zoals Windows Forms en Windows Presentation Foundation (WPF), bieden u alleen toegang tot GUI-objecten vanuit de thread waarmee de gebruikersinterface (de hoofd- of ui-thread) wordt gemaakt en beheerd. Er InvalidOperationException wordt een gegenereerd wanneer u probeert toegang te krijgen tot een UI-element vanuit een andere thread dan de UI-thread. De tekst van het uitzonderingsbericht wordt weergegeven in de volgende tabel.

Toepassingstype Bericht
WPF-app De aanroepende thread heeft geen toegang tot dit object omdat een andere thread eigenaar is van het object.
UWP-app De toepassing heeft een interface genoemd die voor een andere thread werd marshaled.
Windows Forms-app Bewerking voor meerdere threads is ongeldig: Besturingselement 'Tekstvak1' dat is geopend vanuit een andere thread dan de thread waarop deze is gemaakt.

UI-frameworks voor .NET implementeren een dispatcherpatroon dat een methode bevat om te controleren of een aanroep naar een lid van een UI-element wordt uitgevoerd op de UI-thread en andere methoden om de aanroep op de UI-thread te plannen:

  • Roep in WPF-apps de Dispatcher.CheckAccess methode aan om te bepalen of een methode wordt uitgevoerd op een niet-UI-thread. Deze retourneert true als de methode wordt uitgevoerd op de UI-thread en false anders. Roep een van de overbelastingen van de Dispatcher.Invoke methode aan om de aanroep op de UI-thread te plannen.
  • Controleer in UWP-apps de CoreDispatcher.HasThreadAccess eigenschap om te bepalen of een methode wordt uitgevoerd op een niet-UI-thread. Roep de CoreDispatcher.RunAsync methode aan om een gemachtigde uit te voeren waarmee de UI-thread wordt bijgewerkt.
  • Gebruik in Windows Forms-apps de Control.InvokeRequired eigenschap om te bepalen of een methode wordt uitgevoerd op een niet-UI-thread. Roep een van de overbelastingen van de Control.Invoke methode aan om een gemachtigde uit te voeren waarmee de UI-thread wordt bijgewerkt.

In de volgende voorbeelden ziet u de InvalidOperationException uitzondering die wordt gegenereerd wanneer u probeert een UI-element bij te werken vanuit een andere thread dan de thread die deze heeft gemaakt. Voor elk voorbeeld moet u twee besturingselementen maken:

  • Een tekstvak besturingselement met de naam textBox1. In een Windows Forms-app moet u de Multiline eigenschap instellen op true.
  • Een knop besturingselement met de naam threadExampleBtn. Het voorbeeld bevat een handler, ThreadsExampleBtn_Clickvoor de gebeurtenis van Click de knop.

In elk geval roept de threadExampleBtn_Click gebeurtenishandler de DoSomeWork methode twee keer aan. De eerste aanroep wordt synchroon uitgevoerd en slaagt. Maar de tweede aanroep, omdat deze asynchroon wordt uitgevoerd op een thread van een thread met threads, probeert de gebruikersinterface bij te werken vanuit een niet-UI-thread. Dit resulteert in een InvalidOperationException uitzondering.

WPF-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;
}

De volgende versie van de DoSomeWork methode elimineert de uitzondering in een 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; });
}

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

De volgende versie van de DoSomeWork methode elimineert de uitzondering in een 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

Een verzameling wijzigen tijdens het herhalen

De foreach instructie in C#, for...in in F# of For Each instructie in Visual Basic wordt gebruikt om de leden van een verzameling te herhalen en de afzonderlijke elementen ervan te lezen of te wijzigen. Het kan echter niet worden gebruikt om items toe te voegen aan of te verwijderen uit de verzameling. Als u dit doet, wordt er een InvalidOperationException uitzondering gegenereerd met een bericht dat vergelijkbaar is met 'Verzameling is gewijzigd; opsommingsbewerking kan niet worden uitgevoerd.'

In het volgende voorbeeld wordt een verzameling gehele getallen herhaald om het vierkant van elk geheel getal toe te voegen aan de verzameling. Het voorbeeld genereert een InvalidOperationException met de eerste aanroep naar de List<T>.Add methode.

using System;
using System.Collections.Generic;

public class IteratingEx1
{
    public static void Main()
    {
        var numbers = new List<int>() { 1, 2, 3, 4, 5 };
        foreach (var number in numbers)
        {
            int square = (int)Math.Pow(number, 2);
            Console.WriteLine("{0}^{1}", number, square);
            Console.WriteLine("Adding {0} to the collection...\n", square);
            numbers.Add(square);
        }
    }
}
// The example displays the following output:
//    1^1
//    Adding 1 to the collection...
//
//
//    Unhandled Exception: System.InvalidOperationException: Collection was modified;
//       enumeration operation may not execute.
//       at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
//       at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
//       at Example.Main()
open System

let numbers = ResizeArray [| 1; 2; 3; 4; 5 |]
for number in numbers do
    let square = Math.Pow(number, 2) |> int
    printfn $"{number}^{square}"
    printfn $"Adding {square} to the collection...\n"
    numbers.Add square

// The example displays the following output:
//    1^1
//    Adding 1 to the collection...
//
//
//    Unhandled Exception: System.InvalidOperationException: Collection was modified
//       enumeration operation may not execute.
//       at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
//       at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
//       at <StartupCode$fs>.main()
Imports System.Collections.Generic

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

U kunt de uitzondering op twee manieren elimineren, afhankelijk van uw toepassingslogica:

  • Als elementen moeten worden toegevoegd aan de verzameling tijdens het herhalen, kunt u deze herhalen met behulp van de for instructie (for..to in F#) in plaats van foreach, for...inof For Each. In het volgende voorbeeld wordt de for-instructie gebruikt om het kwadrat van getallen in de verzameling toe te voegen aan de verzameling.

    using System;
    using System.Collections.Generic;
    
    public class IteratingEx2
    {
        public static void Main()
        {
            var numbers = new List<int>() { 1, 2, 3, 4, 5 };
    
            int upperBound = numbers.Count - 1;
            for (int ctr = 0; ctr <= upperBound; ctr++)
            {
                int square = (int)Math.Pow(numbers[ctr], 2);
                Console.WriteLine("{0}^{1}", numbers[ctr], square);
                Console.WriteLine("Adding {0} to the collection...\n", square);
                numbers.Add(square);
            }
    
            Console.WriteLine("Elements now in the collection: ");
            foreach (var number in numbers)
                Console.Write("{0}    ", number);
        }
    }
    // The example displays the following output:
    //    1^1
    //    Adding 1 to the collection...
    //
    //    2^4
    //    Adding 4 to the collection...
    //
    //    3^9
    //    Adding 9 to the collection...
    //
    //    4^16
    //    Adding 16 to the collection...
    //
    //    5^25
    //    Adding 25 to the collection...
    //
    //    Elements now in the collection:
    //    1    2    3    4    5    1    4    9    16    25
    
    open System
    open System.Collections.Generic
    
    let numbers = ResizeArray [| 1; 2; 3; 4; 5 |]
    
    let upperBound = numbers.Count - 1
    for i = 0 to upperBound do
        let square = Math.Pow(numbers[i], 2) |> int
        printfn $"{numbers[i]}^{square}"
        printfn $"Adding {square} to the collection...\n"
        numbers.Add square
    
    printfn "Elements now in the collection: "
    for number in numbers do
        printf $"{number}    "
    // The example displays the following output:
    //    1^1
    //    Adding 1 to the collection...
    //
    //    2^4
    //    Adding 4 to the collection...
    //
    //    3^9
    //    Adding 9 to the collection...
    //
    //    4^16
    //    Adding 16 to the collection...
    //
    //    5^25
    //    Adding 25 to the collection...
    //
    //    Elements now in the collection:
    //    1    2    3    4    5    1    4    9    16    25
    
    Imports System.Collections.Generic
    
    Module Example7
        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
    

    Houd er rekening mee dat u het aantal iteraties moet instellen voordat u de verzameling itereert door een teller in de lus te gebruiken die de lus op de juiste manier verlaat, door achteruit te herhalen, van Count - 1 tot 0, of, zoals in het voorbeeld, door het aantal elementen in de matrix toe te wijzen aan een variabele en deze te gebruiken om de bovengrens van de lus vast te stellen. Als er op elke iteratie een element aan de verzameling wordt toegevoegd, resulteert een eindeloze lus.

  • Als het niet nodig is om elementen toe te voegen aan de verzameling tijdens het herhalen, kunt u de elementen opslaan die moeten worden toegevoegd aan een tijdelijke verzameling die u toevoegt wanneer de verzameling is voltooid. In het volgende voorbeeld wordt deze methode gebruikt om het kwadrat van getallen in een verzameling toe te voegen aan een tijdelijke verzameling en vervolgens de verzamelingen te combineren in één matrixobject.

    using System;
    using System.Collections.Generic;
    
    public class IteratingEx3
    {
        public static void Main()
        {
            var numbers = new List<int>() { 1, 2, 3, 4, 5 };
            var temp = new List<int>();
    
            // Square each number and store it in a temporary collection.
            foreach (var number in numbers)
            {
                int square = (int)Math.Pow(number, 2);
                temp.Add(square);
            }
    
            // Combine the numbers into a single array.
            int[] combined = new int[numbers.Count + temp.Count];
            Array.Copy(numbers.ToArray(), 0, combined, 0, numbers.Count);
            Array.Copy(temp.ToArray(), 0, combined, numbers.Count, temp.Count);
    
            // Iterate the array.
            foreach (var value in combined)
                Console.Write("{0}    ", value);
        }
    }
    // The example displays the following output:
    //       1    2    3    4    5    1    4    9    16    25
    
    open System
    open System.Collections.Generic
    
    let numbers = ResizeArray [| 1; 2; 3; 4; 5 |]
    let temp = ResizeArray()
    
    // Square each number and store it in a temporary collection.
    for number in numbers do
        let square = Math.Pow(number, 2) |> int
        temp.Add square
    
    // Combine the numbers into a single array.
    let combined = Array.zeroCreate<int> (numbers.Count + temp.Count)
    Array.Copy(numbers.ToArray(), 0, combined, 0, numbers.Count)
    Array.Copy(temp.ToArray(), 0, combined, numbers.Count, temp.Count)
    
    // Iterate the array.
    for value in combined do
        printf $"{value}    "
    // The example displays the following output:
    //       1    2    3    4    5    1    4    9    16    25
    
    Imports System.Collections.Generic
    
    Module Example8
        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
    

Een matrix of verzameling sorteren waarvan objecten niet kunnen worden vergeleken

Sorteermethoden voor algemeen gebruik, zoals de Array.Sort(Array) methode of de List<T>.Sort() methode, vereisen meestal dat ten minste één van de objecten moet worden gesorteerd op de IComparable<T> interface of de IComparable interface. Zo niet, kan de verzameling of matrix niet worden gesorteerd en de methode genereert een InvalidOperationException uitzondering. In het volgende voorbeeld wordt een Person klasse gedefinieerd, worden twee Person objecten opgeslagen in een algemeen List<T> object en wordt geprobeerd deze te sorteren. Zoals de uitvoer uit het voorbeeld laat zien, genereert de aanroep naar de List<T>.Sort() methode een InvalidOperationException.

using System;
using System.Collections.Generic;

public class Person1
{
    public Person1(string fName, string lName)
    {
        FirstName = fName;
        LastName = lName;
    }

    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public class ListSortEx1
{
    public static void Main()
    {
        var people = new List<Person1>();

        people.Add(new Person1("John", "Doe"));
        people.Add(new Person1("Jane", "Doe"));
        people.Sort();
        foreach (var person in people)
            Console.WriteLine("{0} {1}", person.FirstName, person.LastName);
    }
}
// The example displays the following output:
//    Unhandled Exception: System.InvalidOperationException: Failed to compare two elements in the array. --->
//       System.ArgumentException: At least one object must implement IComparable.
//       at System.Collections.Comparer.Compare(Object a, Object b)
//       at System.Collections.Generic.ArraySortHelper`1.SwapIfGreater(T[] keys, IComparer`1 comparer, Int32 a, Int32 b)
//       at System.Collections.Generic.ArraySortHelper`1.DepthLimitedQuickSort(T[] keys, Int32 left, Int32 right, IComparer`1 comparer, Int32 depthLimit)
//       at System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index, Int32 length, IComparer`1 comparer)
//       --- End of inner exception stack trace ---
//       at System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index, Int32 length, IComparer`1 comparer)
//       at System.Array.Sort[T](T[] array, Int32 index, Int32 length, IComparer`1 comparer)
//       at System.Collections.Generic.List`1.Sort(Int32 index, Int32 count, IComparer`1 comparer)
//       at Example.Main()
type Person(firstName: string, lastName: string) =
    member val FirstName = firstName with get, set
    member val LastName = lastName with get, set

let people = ResizeArray()

people.Add(Person("John", "Doe"))
people.Add(Person("Jane", "Doe"))
people.Sort()
for person in people do
    printfn $"{person.FirstName} {person.LastName}"
// The example displays the following output:
//    Unhandled Exception: System.InvalidOperationException: Failed to compare two elements in the array. --->
//       System.ArgumentException: At least one object must implement IComparable.
//       at System.Collections.Comparer.Compare(Object a, Object b)
//       at System.Collections.Generic.ArraySortHelper`1.SwapIfGreater(T[] keys, IComparer`1 comparer, Int32 a, Int32 b)
//       at System.Collections.Generic.ArraySortHelper`1.DepthLimitedQuickSort(T[] keys, Int32 left, Int32 right, IComparer`1 comparer, Int32 depthLimit)
//       at System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index, Int32 length, IComparer`1 comparer)
//       --- End of inner exception stack trace ---
//       at System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index, Int32 length, IComparer`1 comparer)
//       at System.Array.Sort[T](T[] array, Int32 index, Int32 length, IComparer`1 comparer)
//       at System.Collections.Generic.List`1.Sort(Int32 index, Int32 count, IComparer`1 comparer)
//       at <StartupCode$fs>.main()
Imports System.Collections.Generic

Public Class Person9
    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 Example9
    Public Sub Main()
        Dim people As New List(Of Person9)()

        people.Add(New Person9("John", "Doe"))
        people.Add(New Person9("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()

U kunt de uitzondering op drie manieren elimineren:

  • Als u de eigenaar kunt zijn van het type dat u probeert te sorteren (dat wil zeggen, als u de broncode bepaalt), kunt u dit wijzigen om de IComparable<T> interface of de IComparable interface te implementeren. Hiervoor moet u de IComparable<T>.CompareTo of de CompareTo methode implementeren. Het toevoegen van een interface-implementatie aan een bestaand type is geen belangrijke wijziging.

    In het volgende voorbeeld wordt deze benadering gebruikt om een IComparable<T> implementatie voor de Person klasse te bieden. U kunt de algemene sorteermethode van de verzameling of matrix nog steeds aanroepen en, zoals de uitvoer uit het voorbeeld laat zien, wordt de verzameling gesorteerd.

    using System;
    using System.Collections.Generic;
    
    public class Person2 : IComparable<Person>
    {
        public Person2(String fName, String lName)
        {
            FirstName = fName;
            LastName = lName;
        }
    
        public String FirstName { get; set; }
        public String LastName { get; set; }
    
        public int CompareTo(Person other)
        {
            return String.Format("{0} {1}", LastName, FirstName).
                   CompareTo(String.Format("{0} {1}", other.LastName, other.FirstName));
        }
    }
    
    public class ListSortEx2
    {
        public static void Main()
        {
            var people = new List<Person2>();
    
            people.Add(new Person2("John", "Doe"));
            people.Add(new Person2("Jane", "Doe"));
            people.Sort();
            foreach (var person in people)
                Console.WriteLine("{0} {1}", person.FirstName, person.LastName);
        }
    }
    // The example displays the following output:
    //       Jane Doe
    //       John Doe
    
    open System
    
    type Person(firstName: string, lastName: string) =
        member val FirstName = firstName with get, set
        member val LastName = lastName with get, set
        
        interface IComparable<Person> with
            member this.CompareTo(other) =
                compare $"{this.LastName} {this.FirstName}" $"{other.LastName} {other.FirstName}"
    
    let people = ResizeArray()
    
    people.Add(new Person("John", "Doe"))
    people.Add(new Person("Jane", "Doe"))
    people.Sort()
    for person in people do
        printfn $"{person.FirstName} {person.LastName}"
    // The example displays the following output:
    //       Jane Doe
    //       John Doe
    
    Imports System.Collections.Generic
    
    Public Class Person : Implements IComparable(Of Person)
       Public Sub New(fName As String, lName As String)
          FirstName = fName
          LastName = lName
       End Sub
       
       Public Property FirstName As String
       Public Property LastName As String
       
       Public Function CompareTo(other As Person) As Integer _
              Implements IComparable(Of Person).CompareTo
          Return String.Format("{0} {1}", LastName, FirstName).
                CompareTo(String.Format("{0} {1}", other.LastName, other.FirstName))    
       End Function
    End Class
    
    Module Example10
        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
    
  • Als u de broncode niet kunt wijzigen voor het type dat u wilt sorteren, kunt u een sorteerklasse voor speciaal doel definiëren waarmee de IComparer<T> interface wordt geïmplementeerd. U kunt een overbelasting aanroepen van de Sort methode die een IComparer<T> parameter bevat. Deze methode is vooral handig als u een speciale sorteerklasse wilt ontwikkelen waarmee objecten kunnen worden gesorteerd op basis van meerdere criteria.

    In het volgende voorbeeld wordt de benadering gebruikt door een aangepaste PersonComparer klasse te ontwikkelen die wordt gebruikt om verzamelingen te sorteren Person . Vervolgens wordt een exemplaar van deze klasse doorgegeven aan de List<T>.Sort(IComparer<T>) methode.

    using System;
    using System.Collections.Generic;
    
    public class Person3
    {
        public Person3(String fName, String lName)
        {
            FirstName = fName;
            LastName = lName;
        }
    
        public String FirstName { get; set; }
        public String LastName { get; set; }
    }
    
    public class PersonComparer : IComparer<Person3>
    {
        public int Compare(Person3 x, Person3 y)
        {
            return String.Format("{0} {1}", x.LastName, x.FirstName).
                   CompareTo(String.Format("{0} {1}", y.LastName, y.FirstName));
        }
    }
    
    public class ListSortEx3
    {
        public static void Main()
        {
            var people = new List<Person3>();
    
            people.Add(new Person3("John", "Doe"));
            people.Add(new Person3("Jane", "Doe"));
            people.Sort(new PersonComparer());
            foreach (var person in people)
                Console.WriteLine("{0} {1}", person.FirstName, person.LastName);
        }
    }
    // The example displays the following output:
    //       Jane Doe
    //       John Doe
    
    open System
    open System.Collections.Generic
    
    type Person(firstName, lastName) =
        member val FirstName = firstName with get, set
        member val LastName = lastName with get, set
    
    type PersonComparer() =
        interface IComparer<Person> with
            member _.Compare(x: Person, y: Person) =
                $"{x.LastName} {x.FirstName}".CompareTo $"{y.LastName} {y.FirstName}"
    
    let people = ResizeArray()
    
    people.Add(Person("John", "Doe"))
    people.Add(Person("Jane", "Doe"))
    people.Sort(PersonComparer())
    for person in people do
        printfn $"{person.FirstName} {person.LastName}"
    // The example displays the following output:
    //       Jane Doe
    //       John Doe
    
    Imports System.Collections.Generic
    
    Public Class Person11
        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 Person11)
        Public Function Compare(x As Person11, y As Person11) As Integer _
              Implements IComparer(Of Person11).Compare
            Return String.Format("{0} {1}", x.LastName, x.FirstName).
                 CompareTo(String.Format("{0} {1}", y.LastName, y.FirstName))
        End Function
    End Class
    
    Module Example11
        Public Sub Main()
            Dim people As New List(Of Person11)()
    
            people.Add(New Person11("John", "Doe"))
            people.Add(New Person11("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
    
  • Als u de broncode voor het type dat u wilt sorteren niet kunt wijzigen, kunt u een Comparison<T> gemachtigde maken om de sortering uit te voeren. De handtekening van de gemachtigde is

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

    In het volgende voorbeeld wordt de methode gebruikt door een PersonComparison methode te definiëren die overeenkomt met de handtekening van de Comparison<T> gemachtigde. Vervolgens wordt deze gemachtigde doorgegeven aan de List<T>.Sort(Comparison<T>) methode.

    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 ListSortEx4
    {
       public static void Main()
       {
          var people = new List<Person>();
    
          people.Add(new Person("John", "Doe"));
          people.Add(new Person("Jane", "Doe"));
          people.Sort(PersonComparison);
          foreach (var person in people)
             Console.WriteLine("{0} {1}", person.FirstName, person.LastName);
       }
    
       public static int PersonComparison(Person x, Person y)
       {
          return String.Format("{0} {1}", x.LastName, x.FirstName).
                 CompareTo(String.Format("{0} {1}", y.LastName, y.FirstName));
       }
    }
    // The example displays the following output:
    //       Jane Doe
    //       John Doe
    
    open System
    open System.Collections.Generic
    
    type Person(firstName, lastName) =
        member val FirstName = firstName with get, set
        member val LastName = lastName with get, set
    
    let personComparison (x: Person) (y: Person) =
        $"{x.LastName} {x.FirstName}".CompareTo $"{y.LastName} {y.FirstName}"
    
    let people = ResizeArray()
    
    people.Add(Person("John", "Doe"))
    people.Add(Person("Jane", "Doe"))
    people.Sort personComparison
    for person in people do
        printfn $"{person.FirstName} {person.LastName}"
    
    // The example displays the following output:
    //       Jane Doe
    //       John Doe
    
    Imports System.Collections.Generic
    
    Public Class Person12
        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 Example12
        Public Sub Main()
            Dim people As New List(Of Person12)()
    
            people.Add(New Person12("John", "Doe"))
            people.Add(New Person12("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 Person12, y As Person12) 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
    

Het casten van een nullable<T> die null is naar het onderliggende type

Als u een Nullable<T> waarde probeert te casten die is null gekoppeld aan het onderliggende type, wordt er een InvalidOperationException uitzondering gegenereerd en wordt het foutbericht weergegeven: 'Nullable object moet een waarde hebben.

In het volgende voorbeeld wordt een InvalidOperationException uitzondering gegenereerd wanneer wordt geprobeerd een matrix te herhalen die een Nullable(Of Integer) waarde bevat.

using System;
using System.Linq;

public class NullableEx1
{
   public static void Main()
   {
      var queryResult = new int?[] { 1, 2, null, 4 };
      var map = queryResult.Select(nullableInt => (int)nullableInt);

      // Display list.
      foreach (var num in map)
         Console.Write("{0} ", num);
      Console.WriteLine();
   }
}
// The example displays the following output:
//    1 2
//    Unhandled Exception: System.InvalidOperationException: Nullable object must have a value.
//       at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
//       at Example.<Main>b__0(Nullable`1 nullableInt)
//       at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
//       at Example.Main()
open System
open System.Linq

let queryResult = [| Nullable 1; Nullable 2; Nullable(); Nullable 4 |]
let map = queryResult.Select(fun nullableInt -> nullableInt.Value)

// Display list.
for num in map do
    printf $"{num} "
printfn ""
// The example displays the following output:
//    1 2
//    Unhandled Exception: System.InvalidOperationException: Nullable object must have a value.
//       at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
//       at Example.<Main>b__0(Nullable`1 nullableInt)
//       at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
//       at <StartupCode$fs>.main()
Imports System.Linq

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

Ga als volgende te werk om de uitzondering te voorkomen:

In het volgende voorbeeld worden beide gebruikt om de InvalidOperationException uitzondering te voorkomen.

using System;
using System.Linq;

public class NullableEx2
{
   public static void Main()
   {
      var queryResult = new int?[] { 1, 2, null, 4 };
      var numbers = queryResult.Select(nullableInt => (int)nullableInt.GetValueOrDefault());

      // Display list using Nullable<int>.HasValue.
      foreach (var number in numbers)
         Console.Write("{0} ", number);
      Console.WriteLine();

      numbers = queryResult.Select(nullableInt => (int) (nullableInt.HasValue ? nullableInt : -1));
      // Display list using Nullable<int>.GetValueOrDefault.
      foreach (var number in numbers)
         Console.Write("{0} ", number);
      Console.WriteLine();
   }
}
// The example displays the following output:
//       1 2 0 4
//       1 2 -1 4
open System
open System.Linq

let queryResult = [| Nullable 1; Nullable 2; Nullable(); Nullable 4 |]
let numbers = queryResult.Select(fun nullableInt -> nullableInt.GetValueOrDefault())

// Display list using Nullable<int>.HasValue.
for number in numbers do
    printf $"{number} "
printfn ""

let numbers2 = queryResult.Select(fun nullableInt -> if nullableInt.HasValue then nullableInt.Value else -1)
// Display list using Nullable<int>.GetValueOrDefault.
for number in numbers2 do
    printf $"{number} "
printfn ""
// The example displays the following output:
//       1 2 0 4
//       1 2 -1 4
Imports System.Linq

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

Een System.Linq.Enumerable-methode aanroepen voor een lege verzameling

De Enumerable.Aggregatemethoden , , Enumerable.Average, Enumerable.FirstEnumerable.Last, Enumerable.Max, en Enumerable.MinEnumerable.SingleEnumerable.SingleOrDefault methoden voeren bewerkingen uit op een reeks en retourneren één resultaat. Sommige overbelastingen van deze methoden veroorzaken een InvalidOperationException uitzondering wanneer de reeks leeg is, terwijl andere overbelastingen retourneren null. De Enumerable.SingleOrDefault methode genereert ook een InvalidOperationException uitzondering wanneer de reeks meer dan één element bevat.

Notitie

De meeste methoden die een InvalidOperationException uitzondering veroorzaken, zijn overbelast. Zorg ervoor dat u het gedrag begrijpt van de overbelasting die u kiest.

De volgende tabel bevat de uitzonderingsberichten van de InvalidOperationException uitzonderingsobjecten die worden gegenereerd door aanroepen naar een aantal System.Linq.Enumerable methoden.

Wijze Bericht
Aggregate
Average
Last
Max
Min
Reeks bevat geen elementen
First Reeks bevat geen overeenkomend element
Single
SingleOrDefault
Reeks bevat meer dan één overeenkomend element

Hoe u de uitzondering elimineert of afhandelt, is afhankelijk van de veronderstellingen van uw toepassing en van de specifieke methode die u aanroept.

  • Wanneer u bewust een van deze methoden aanroept zonder te controleren op een lege reeks, gaat u ervan uit dat de reeks niet leeg is en dat een lege reeks een onverwachte gebeurtenis is. In dit geval is het passend om de uitzondering te vangen of opnieuw te beperken.

  • Als uw fout bij het controleren op een lege reeks per ongeluk is mislukt, kunt u een van de overbelastingen van de Enumerable.Any overbelasting aanroepen om te bepalen of een reeks elementen bevat.

    Tip

    Het aanroepen van de Enumerable.Any<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>) methode voordat een reeks wordt gegenereerd, kan de prestaties verbeteren als de te verwerken gegevens een groot aantal elementen kunnen bevatten of als de bewerking waarmee de reeks wordt gegenereerd duur is.

  • Als u een methode hebt aangeroepen, zoals Enumerable.First, Enumerable.Lastof Enumerable.Single, kunt u een alternatieve methode vervangen, zoals Enumerable.FirstOrDefault, Enumerable.LastOrDefaultof Enumerable.SingleOrDefault, die een standaardwaarde retourneert in plaats van een lid van de reeks.

De voorbeelden bevatten aanvullende details.

In het volgende voorbeeld wordt de Enumerable.Average methode gebruikt om het gemiddelde van een reeks te berekenen waarvan de waarden groter zijn dan 4. Omdat er geen waarden uit de oorspronkelijke matrix groter zijn dan 4, worden er geen waarden opgenomen in de reeks en genereert de methode een InvalidOperationException uitzondering.

using System;
using System.Linq;

public class Example
{
   public static void Main()
   {
      int[] data = { 1, 2, 3, 4 };
      var average = data.Where(num => num > 4).Average();
      Console.Write("The average of numbers greater than 4 is {0}",
                    average);
   }
}
// The example displays the following output:
//    Unhandled Exception: System.InvalidOperationException: Sequence contains no elements
//       at System.Linq.Enumerable.Average(IEnumerable`1 source)
//       at Example.Main()
open System
open System.Linq

let data = [| 1; 2; 3; 4 |]
let average = 
   data.Where(fun num -> num > 4).Average();
printfn $"The average of numbers greater than 4 is {average}"
// The example displays the following output:
//    Unhandled Exception: System.InvalidOperationException: Sequence contains no elements
//       at System.Linq.Enumerable.Average(IEnumerable`1 source)
//       at <StartupCode$fs>.main()
Imports System.Linq

Module Example
   Public Sub Main()
      Dim data() As Integer = { 1, 2, 3, 4 }
      Dim average = data.Where(Function(num) num > 4).Average()
      Console.Write("The average of numbers greater than 4 is {0}",
                    average)
   End Sub
End Module
' The example displays the following output:
'    Unhandled Exception: System.InvalidOperationException: Sequence contains no elements
'       at System.Linq.Enumerable.Average(IEnumerable`1 source)
'       at Example.Main()

De uitzondering kan worden geëlimineerd door de Any methode aan te roepen om te bepalen of de reeks elementen bevat voordat u de methode aanroept die de reeks verwerkt, zoals in het volgende voorbeeld wordt weergegeven.

using System;
using System.Linq;

public class EnumerableEx2
{
    public static void Main()
    {
        int[] dbQueryResults = { 1, 2, 3, 4 };
        var moreThan4 = dbQueryResults.Where(num => num > 4);

        if (moreThan4.Any())
            Console.WriteLine("Average value of numbers greater than 4: {0}:",
                              moreThan4.Average());
        else
            // handle empty collection
            Console.WriteLine("The dataset has no values greater than 4.");
    }
}
// The example displays the following output:
//       The dataset has no values greater than 4.
open System
open System.Linq

let dbQueryResults = [| 1; 2; 3; 4 |]
let moreThan4 = 
    dbQueryResults.Where(fun num -> num > 4)

if moreThan4.Any() then
    printfn $"Average value of numbers greater than 4: {moreThan4.Average()}:"
else
    // handle empty collection
    printfn "The dataset has no values greater than 4."

// The example displays the following output:
//       The dataset has no values greater than 4.
Imports System.Linq

Module Example1
    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.

De Enumerable.First methode retourneert het eerste item in een reeks of het eerste element in een reeks die voldoet aan een opgegeven voorwaarde. Als de reeks leeg is en dus geen eerste element heeft, wordt er een InvalidOperationException uitzondering gegenereerd.

In het volgende voorbeeld genereert de Enumerable.First<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>) methode een InvalidOperationException uitzondering omdat de matrix dbQueryResults geen element bevat dat groter is dan 4.

using System;
using System.Linq;

public class EnumerableEx3
{
    public static void Main()
    {
        int[] dbQueryResults = { 1, 2, 3, 4 };

        var firstNum = dbQueryResults.First(n => n > 4);

        Console.WriteLine("The first value greater than 4 is {0}",
                          firstNum);
    }
}
// The example displays the following output:
//    Unhandled Exception: System.InvalidOperationException:
//       Sequence contains no matching element
//       at System.Linq.Enumerable.First[TSource](IEnumerable`1 source, Func`2 predicate)
//       at Example.Main()
open System
open System.Linq

let dbQueryResults = [| 1; 2; 3; 4 |]

let firstNum = dbQueryResults.First(fun n -> n > 4)

printfn $"The first value greater than 4 is {firstNum}"

// The example displays the following output:
//    Unhandled Exception: System.InvalidOperationException:
//       Sequence contains no matching element
//       at System.Linq.Enumerable.First[TSource](IEnumerable`1 source, Func`2 predicate)
//       at <StartupCode$fs>.main()
Imports System.Linq

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

U kunt de Enumerable.FirstOrDefault methode aanroepen in plaats van Enumerable.First een opgegeven of standaardwaarde te retourneren. Als de methode geen eerste element in de reeks vindt, wordt de standaardwaarde voor dat gegevenstype geretourneerd. De standaardwaarde is null voor een verwijzingstype, nul voor een numeriek gegevenstype en DateTime.MinValue voor het DateTime type.

Notitie

Het interpreteren van de waarde die door de Enumerable.FirstOrDefault methode wordt geretourneerd, wordt vaak gecompliceerd door het feit dat de standaardwaarde van het type een geldige waarde in de reeks kan zijn. In dit geval roept u de Enumerable.Any methode aan om te bepalen of de reeks geldige leden heeft voordat u de Enumerable.First methode aanroept.

In het volgende voorbeeld wordt de Enumerable.FirstOrDefault<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>) methode aangeroepen om te voorkomen dat de InvalidOperationException uitzondering die is opgetreden in het vorige voorbeeld.

using System;
using System.Linq;

public class EnumerableEx4
{
    public static void Main()
    {
        int[] dbQueryResults = { 1, 2, 3, 4 };

        var firstNum = dbQueryResults.FirstOrDefault(n => n > 4);

        if (firstNum == 0)
            Console.WriteLine("No value is greater than 4.");
        else
            Console.WriteLine("The first value greater than 4 is {0}",
                              firstNum);
    }
}
// The example displays the following output:
//       No value is greater than 4.
open System
open System.Linq

let dbQueryResults = [| 1; 2; 3; 4 |]

let firstNum = dbQueryResults.FirstOrDefault(fun n -> n > 4)

if firstNum = 0 then
    printfn "No value is greater than 4."
else
    printfn $"The first value greater than 4 is {firstNum}"

// The example displays the following output:
//       No value is greater than 4.
Imports System.Linq

Module Example3
    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 of Enumerable.SingleOrDefault aanroepen op een reeks zonder één element

De Enumerable.Single methode retourneert het enige element van een reeks of het enige element van een reeks dat voldoet aan een opgegeven voorwaarde. Als er geen elementen in de reeks staan of als er meer dan één element is, genereert de methode een InvalidOperationException uitzondering.

U kunt de Enumerable.SingleOrDefault methode gebruiken om een standaardwaarde te retourneren in plaats van een uitzondering te genereren wanneer de reeks geen elementen bevat. De Enumerable.SingleOrDefault methode genereert echter nog steeds een InvalidOperationException uitzondering wanneer de reeks meer dan één element bevat.

De volgende tabel bevat de uitzonderingsberichten van de InvalidOperationException uitzonderingsobjecten die worden gegenereerd door aanroepen naar de Enumerable.Single en Enumerable.SingleOrDefault methoden.

Wijze Bericht
Single Reeks bevat geen overeenkomend element
Single
SingleOrDefault
Reeks bevat meer dan één overeenkomend element

In het volgende voorbeeld genereert de aanroep van de Enumerable.Single methode een InvalidOperationException uitzondering omdat de reeks geen element groter dan 4 heeft.

using System;
using System.Linq;

public class EnumerableEx5
{
    public static void Main()
    {
        int[] dbQueryResults = { 1, 2, 3, 4 };

        var singleObject = dbQueryResults.Single(value => value > 4);

        // Display results.
        Console.WriteLine("{0} is the only value greater than 4", singleObject);
    }
}
// The example displays the following output:
//    Unhandled Exception: System.InvalidOperationException:
//       Sequence contains no matching element
//       at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source, Func`2 predicate)
//       at Example.Main()
open System
open System.Linq

let dbQueryResults = [| 1; 2; 3; 4 |]

let singleObject = dbQueryResults.Single(fun value -> value > 4)

// Display results.
printfn $"{singleObject} is the only value greater than 4"

// The example displays the following output:
//    Unhandled Exception: System.InvalidOperationException:
//       Sequence contains no matching element
//       at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source, Func`2 predicate)
//       at <StartupCode$fs>.main()
Imports System.Linq

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

In het volgende voorbeeld wordt geprobeerd te voorkomen dat de InvalidOperationException uitzondering wordt gegenereerd wanneer een reeks leeg is door in plaats daarvan de methode aan te Enumerable.SingleOrDefault roepen. Omdat deze reeks echter meerdere elementen retourneert waarvan de waarde groter is dan 2, genereert deze ook een InvalidOperationException uitzondering.

using System;
using System.Linq;

public class EnumerableEx6
{
    public static void Main()
    {
        int[] dbQueryResults = { 1, 2, 3, 4 };

        var singleObject = dbQueryResults.SingleOrDefault(value => value > 2);

        if (singleObject != 0)
            Console.WriteLine("{0} is the only value greater than 2",
                              singleObject);
        else
            // Handle an empty collection.
            Console.WriteLine("No value is greater than 2");
    }
}
// The example displays the following output:
//    Unhandled Exception: System.InvalidOperationException:
//       Sequence contains more than one matching element
//       at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source, Func`2 predicate)
//       at Example.Main()
open System
open System.Linq

let dbQueryResults = [| 1; 2; 3; 4 |]

let singleObject = dbQueryResults.SingleOrDefault(fun value -> value > 2)

if singleObject <> 0 then
    printfn $"{singleObject} is the only value greater than 2"
else
    // Handle an empty collection.
    printfn "No value is greater than 2"
    
// The example displays the following output:
//    Unhandled Exception: System.InvalidOperationException:
//       Sequence contains more than one matching element
//       at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source, Func`2 predicate)
//       at <StartupCode$fs>.main()
Imports System.Linq

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

Bij het aanroepen van de Enumerable.Single methode wordt ervan uitgegaan dat een reeks of de reeks die voldoet aan opgegeven criteria slechts één element bevat. Enumerable.SingleOrDefault gaat ervan uit dat een reeks met nul of één resultaat, maar niet meer. Als deze aanname een opzettelijke aanname is en deze voorwaarden niet worden voldaan, is het opnieuw beperken of vangen van het resulterende InvalidOperationException resultaat passend. Anders, of als u verwacht dat ongeldige voorwaarden met een bepaalde frequentie optreden, moet u overwegen een andere Enumerable methode te gebruiken, zoals FirstOrDefault of Where.

Dynamische toegang tot domeindomeinen tussen toepassingen

De OpCodes.Ldflda algemene instructie tussenliggende taal (CIL) genereert een InvalidOperationException uitzondering als het object met het veld waarvan u het adres dat u probeert op te halen zich niet binnen het toepassingsdomein bevindt waarin uw code wordt uitgevoerd. Het adres van een veld kan alleen worden geopend vanuit het toepassingsdomein waarin het zich bevindt.

Een InvalidOperationException-uitzondering genereren

U moet alleen een InvalidOperationException uitzondering genereren wanneer de status van uw object om een of andere reden geen ondersteuning biedt voor een bepaalde methodeaanroep. Dat wil gezegd: de methode-aanroep is in sommige omstandigheden of contexten geldig, maar is ongeldig in andere.

Als de aanroepfout van de methode wordt veroorzaakt door ongeldige argumenten, ArgumentException dan of een van de afgeleide klassen, of ArgumentOutOfRangeExceptionin plaats daarvan, ArgumentNullException moet worden gegenereerd.