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 InvalidOperationException uitzondering wordt bijvoorbeeld gegenereerd door methoden zoals:

  • IEnumerator.MoveNext als objecten van een verzameling worden gewijzigd nadat de enumerator is gemaakt. Zie Een verzameling wijzigen tijdens het herhalenvoor meer informatie.
  • ResourceSet.GetString als de resourceset wordt gesloten voordat de methode-aanroep wordt uitgevoerd.
  • XContainer.Add, als het object of de objecten die moeten worden toegevoegd, een onjuist gestructureerd XML-document oplevert.
  • 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 wordt geretourneerd door de eigenschap Message.

InvalidOperationException gebruikt de HRESULT-COR_E_INVALIDOPERATION, met de waarde 0x80131509.

Voor een lijst van initiële eigenschapswaarden voor een exemplaar van InvalidOperationException, zie de InvalidOperationException-constructoren.

Veelvoorkomende oorzaken van InvalidOperationException-uitzonderingen

In de volgende secties ziet u hoe in sommige veelvoorkomende gevallen de InvalidOperationException-uitzondering in een app optreedt. 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

Werkthreads worden vaak gebruikt om achtergrondwerk uit te voeren waarbij gegevens worden verzameld die in de gebruikersinterface van een toepassing moeten worden weergegeven. 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 wordt een InvalidOperationException 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 dit 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 dispatcher patroon 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. Het retourneert true als de methode wordt uitgevoerd op de UI-thread en anders false. 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 eigenschap CoreDispatcher.HasThreadAccess 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 eigenschap Control.InvokeRequired om te bepalen of een methode wordt uitgevoerd op een niet-UI-thread. Roep een van de overloads van de Control.Invoke-methode aan om een gedelegeerde uit te voeren die de UI-thread bijwerkt.

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 tekstvakcontrole met de naam textBox1. In een Windows Forms-app moet u de bijbehorende eigenschap Multiline instellen op true.
  • Een knop besturingselement met de naam threadExampleBtn. Het voorbeeld bevat een handler, ThreadsExampleBtn_Click, voor het Click event van de knop.

In elk geval roept de threadExampleBtn_Click gebeurtenishandler de DoSomeWork methode tweemaal aan. De eerste aanroep wordt synchroon uitgevoerd en slaagt. Maar de tweede aanroep, omdat deze asynchroon wordt uitgevoerd op een thread van een thread-pool, probeert de gebruikersinterface bij te werken vanuit een niet-gebruikersinterface-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;
}

Met de volgende versie van de methode DoSomeWork wordt de uitzondering in een WPF-app geëlimineerd.

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

Met de volgende versie van de methode DoSomeWork wordt de uitzondering in een Windows Forms-app geëlimineerd.

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 itereren

De instructie foreach 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 lijkt op'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. In het voorbeeld wordt een InvalidOperationException bij de eerste oproep van de methode List<T>.Add.

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($"{number}^{square}");
            Console.WriteLine($"Adding {square} to the collection...");
            Console.WriteLine();
            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 itereren, kunt u deze itereren met behulp van een index met de instructie for (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($"{numbers[ctr]}^{square}");
                Console.WriteLine($"Adding {square} to the collection...");
                Console.WriteLine();
                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 methode Array.Sort(Array) of de methode List<T>.Sort(), vereisen meestal dat ten minste één van de objecten moet worden gesorteerd om de IComparable<T> of de IComparable-interface te implementeren. 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 van de methode List<T>.Sort() 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($"{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> of de IComparable-interface te implementeren. Hiervoor moet u de IComparable<T>.CompareTo of de methode CompareTo implementeren. Het toevoegen van een interface-implementatie aan een bestaand type is geen belangrijke wijziging.

    In het volgende voorbeeld wordt deze methode gebruikt om een IComparable<T>-implementatie te bieden voor de Person-klasse. 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 succesvol 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($"{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 Person verzamelingen te sorteren. Vervolgens wordt een exemplaar van deze klasse doorgegeven aan de methode List<T>.Sort(IComparer<T>).

    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($"{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 niet kunt wijzigen voor het type dat u wilt sorteren, 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 Comparison<T> handtekening voor gemachtigden. Vervolgens wordt deze gemachtigde doorgegeven aan de methode List<T>.Sort(Comparison<T>).

    using System;
    using System.Collections.Generic;
    
    public class Person
    {
       public Person(String fName, String lName)
       {
          FirstName = fName;
          LastName = lName;
       }
    
       public String FirstName { get; set; }
       public String LastName { get; set; }
    }
    
    public class 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($"{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> dat null is naar zijn onderliggende type

Als u een Nullable<T>-waarde probeert te casten die null is naar het onderliggende type, genereert dat een InvalidOperationException-uitzondering 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.Aggregate, Enumerable.Average, Enumerable.First, Enumerable.Last, Enumerable.Max, Enumerable.Min, Enumerable.Singleen Enumerable.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 nullretourneren. De methode Enumerable.SingleOrDefault 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.

Methode 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 hergooien.

  • Als de controle op een lege reeks per ongeluk is mislukt, kunt u een van de overbelastingen van de Enumerable.Any aanroepen om te bepalen of een reeks elementen bevat.

    Hint

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

  • Als u een methode zoals Enumerable.First, Enumerable.Lastof Enumerable.Singlehebt aangeroepen, 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 methode Enumerable.Average 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 methode Any aan te roepen om te bepalen of de reeks elementen bevat voordat de methode wordt aangeroepen 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: {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 methode Enumerable.First 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 methode Enumerable.First<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>) 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 {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 methode Enumerable.FirstOrDefault aanroepen in plaats van Enumerable.First om 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 methode Enumerable.First aanroept.

In het volgende voorbeeld wordt de methode Enumerable.FirstOrDefault<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>) aangeroepen om te voorkomen dat de InvalidOperationException exceptie uit het vorige voorbeeld optreedt.

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 {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 methode Enumerable.Single 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 methode Enumerable.SingleOrDefault gebruiken om een standaardwaarde te retourneren in plaats van een uitzondering te genereren wanneer de reeks geen elementen bevat. De methode Enumerable.SingleOrDefault 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.

Methode 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 methode Enumerable.Single 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($"{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 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 optreedt wanneer een reeks leeg is door in plaats daarvan de Enumerable.SingleOrDefault methode aan te 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($"{singleObject} is the only value greater than 2");
        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 methode Enumerable.Single wordt ervan uitgegaan dat een reeks of de reeks die voldoet aan opgegeven criteria slechts één element bevat. Enumerable.SingleOrDefault gaat uit van een reeks met nul of één resultaat, maar niet meer. Als deze aanname een opzettelijke aanname van uw kant is en niet aan deze voorwaarden wordt voldaan, is het gepast om de resulterende fout InvalidOperationException opnieuw te werpen of op te vangen. Anders, of als u verwacht dat er ongeldige voorwaarden met een bepaalde frequentie zullen optreden, kunt u overwegen een andere Enumerable-methode te gebruiken, zoals FirstOrDefault of Where.

Dynamische toegang tot domeindomeinen tussen toepassingen

De instructie OpCodes.Ldflda algemene tussentaal (CIL) genereert een InvalidOperationException uitzondering als het object met het veld waarvan u het adres wilt ophalen 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 wordt veroorzaakt door ongeldige argumenten, moet in plaats daarvan ArgumentException of een van de afgeleide klassen, ArgumentNullException of ArgumentOutOfRangeException, worden gegooid.