System.InvalidOperationException osztály

Megjegyzés

Ez a cikk kiegészítő megjegyzéseket tartalmaz az API referenciadokumentációjához.

InvalidOperationException olyan esetekben használatos, amikor a metódus meghívásának sikertelenségét nem érvénytelen argumentumok okozzák. Általában akkor történik, ha egy objektum állapota nem támogatja a metódushívást. Például egy InvalidOperationException kivételt a következő metódusok dobhatnak:

  • IEnumerator.MoveNext ha a gyűjtemény objektumai az enumerátor létrehozása után módosulnak. További információ: Gyűjtemény módosítása iterálás közben.
  • ResourceSet.GetString ha az erőforráskészlet a metódushívás előtt le van zárva.
  • XContainer.Add, ha a hozzáadni kívánt objektum vagy objektumok helytelenül strukturált XML-dokumentumot eredményeznének.
  • Olyan módszer, amely a felhasználói felületet olyan szálból próbálja manipulálni, amely nem a fő vagy a felhasználói felület szála.

Fontos

Mivel a InvalidOperationException kivétel sokféle körülmény között kiváltható, fontos elolvasni a Message tulajdonság által visszaadott kivételüzenetet.

InvalidOperationException A HRESULT COR_E_INVALIDOPERATIONfüggvényt használja, amelynek értéke 0x80131509.

A InvalidOperationException példány kezdeti tulajdonságainak listájáért tekintse meg a InvalidOperationException konstruktorokat.

Az InvalidOperationException kivételek gyakori okai

Az alábbi szakaszok bemutatják, hogyan fordul elő kivételdobás egy alkalmazásban bizonyos gyakori esetekben. A probléma kezelése az adott helyzettől függ. A kivétel leggyakrabban azonban fejlesztői hibából ered, és a InvalidOperationException kivétel előre jelezhető és elkerülhető.

Felhasználói felületi szál frissítése nem felhasználói felületi szálról

A feldolgozószálak gyakran olyan háttérmunkát végeznek, amely az alkalmazások felhasználói felületén megjelenítendő adatok gyűjtését foglalja magában. Azonban. A legtöbb grafikus felhasználói felület (grafikus felhasználói felület) alkalmazás-keretrendszer a .NET-hez, például a Windows Formshoz és a Windows Presentation Foundationhez (WPF) csak a felhasználói felületet létrehozó és kezelő szálból (a fő vagy felhasználói felületi szálból) férhet hozzá. A InvalidOperationException felhasználói felületi elemek a felhasználói felületi száltól eltérő szálból való elérésekor kerülnek alkalmazásra. A kivételüzenet szövege az alábbi táblázatban látható.

Alkalmazás típusa Üzenet
WPF-alkalmazás A hívószál nem tudja elérni ezt az objektumot, mert egy másik szál birtokolja.
UWP-alkalmazás Az alkalmazás egy olyan felületet hívott, amelyet egy másik szálhoz rendeltek.
Windows Forms alkalmazás A szálközi művelet nem érvényes: A "TextBox1" vezérlő a létrehozott száltól eltérő szálból érhető el.

A .NET felhasználói felületi keretrendszerei olyan diszpécsermintát implementálnak, amely egy metódust tartalmaz annak ellenőrzésére, hogy a felhasználói felületi elem egy tagjának hívása folyamatban van-e a felhasználói felületen, és egyéb módszerek a hívás felhasználói felületi szálon való ütemezéséhez:

  • A WPF-alkalmazásokban hívja meg a Dispatcher.CheckAccess metódust annak megállapításához, hogy egy metódus nem felhasználói felületen fut-e. Akkor ad true vissza, ha a metódus a felhasználói felületen fut, és false egyébként is. Hívja meg a Dispatcher.Invoke metódus egyik túlterhelését, hogy a hívást ütemezze a felhasználói felület szálára.
  • Az UWP-alkalmazásokban ellenőrizze a CoreDispatcher.HasThreadAccess tulajdonságot annak megállapításához, hogy egy metódus nem felhasználói felületen fut-e. Hívja meg a CoreDispatcher.RunAsync metódust egy olyan meghatalmazott végrehajtásához, amely frissíti a felhasználói felület szálát.
  • A Windows Forms-alkalmazásokban a Control.InvokeRequired tulajdonság használatával állapítsa meg, hogy egy metódus nem felhasználói felületen fut-e. Hívja meg a metódus egyik túlterhelését a Control.Invoke felhasználói felület szálát frissíteni kívánó meghatalmazott végrehajtásához.

Az alábbi példák azt a InvalidOperationException kivételt szemléltetik, amely akkor keletkezik, amikor egy felhasználói felületi elemet nem az azt létrehozó szálból próbál frissíteni. Minden példához két vezérlőt kell létrehoznia:

  • Egy szövegdoboz vezérlőelem neve textBox1. Windows Forms-alkalmazásban be kell állítania a(z) Multiline tulajdonságot a(z) true értékre.
  • A threadExampleBtn nevű gombvezérlő. A példa egy kezelőt biztosít a ThreadsExampleBtn_Click gomb Click eseményéhez.

Az eseménykezelő minden esetben kétszer hívja meg a threadExampleBtn_Click metódust. Az első hívás szinkron módon fut, és sikeres. A második hívás azonban, mivel aszinkron módon fut a szálkészlet egyik szálán, megpróbálja frissíteni a felhasználói felületet egy nem felhasználói felülethez tartozó szálról. Ez InvalidOperationException kivételt eredményez.

WPF-alkalmazások

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

A módszer következő verziója DoSomeWork megszünteti a WPF-alkalmazások kivételét.

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-alkalmazások

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

A metódus alábbi verziója DoSomeWork megszünteti a Kivételt a Windows Forms-alkalmazásokban.

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

Gyűjtemény módosítása iterálás közben

A foreach C#-ban, for...in F#-ban vagy For Each a Visual Basicben található utasítás a gyűjtemény tagjainak iterálására, valamint az egyes elemek olvasására vagy módosítására szolgál. Azonban nem használható elemek hozzáadására vagy eltávolítására a gyűjteményből. Ez a művelet kivételt InvalidOperationException eredményez a következőhöz hasonló üzenettel: "A gyűjtemény módosult; az enumerálási művelet nem hajtható végre."

Az alábbi példa egy egész számgyűjteményt iterál, amely az egyes egész számok négyzetét próbálja hozzáadni a gyűjteményhez. A példa a InvalidOperationException metódus első hívásával indítja el a List<T>.Add hívást.

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

A kivételt az alkalmazáslogikától függően kétféleképpen szüntetheti meg:

  • Ha elemeket kell hozzáadni a gyűjteményhez annak iterálása során, akkor index alapján iterálhatja azt a for (for..to F#-ban) utasítással, ahelyett, hogy a foreach, for...in vagy For Each utasításokat használná. Az alábbi példa a for utasítás használatával adja hozzá a gyűjteményben lévő számok négyzetét a gyűjteményhez.

    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
    

    Vegye figyelembe, hogy a gyűjtemény iterálása előtt meg kell határoznia az iterációk számát az alábbi módok egyikével: egy számláló használata a cikluson belül, amely megfelelően szabályozza a ciklusból való kilépést, visszafelé iterálás Count - 1-től 0-ig, vagy, ahogy a példa mutatja, úgy, hogy a tömb elemeinek számát egy változóhoz rendeli, és ezt használja a ciklus felső határának meghatározásához. Ellenkező esetben, ha minden iterációban hozzáad egy elemet a gyűjteményhez, végtelen ciklus jön létre.

  • Ha az iterálás során nem szükséges elemeket hozzáadni a gyűjteményhez, a hozzáadni kívánt elemeket egy ideiglenes gyűjteményben tárolhatja, amelyet a gyűjtemény iterálása során ad hozzá. Az alábbi példa ezzel a módszerrel adja hozzá egy gyűjtemény számainak négyzetét egy ideiglenes gyűjteményhez, majd egyesítse a gyűjteményeket egyetlen tömbobjektumban.

    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
    

Olyan tömb vagy gyűjtemény rendezése, amelynek objektumai nem hasonlíthatók össze

Az általános célú rendezési módszerek, mint például a Array.Sort(Array) metódus vagy a List<T>.Sort() módszer, általában megkövetelik, hogy a rendezendő objektumok közül legalább egy implementálja a IComparable<T> vagy a IComparable interfészt. Ha nem, a gyűjtemény vagy a tömb nem rendezhető, és a metódus kivételt InvalidOperationException eredményez. Az alábbi példa egy osztályt Person határoz meg, két Person objektumot tárol egy általános List<T> objektumban, és megpróbálja rendezni őket. Ahogy a példa kimenete is mutatja, a metódus hívása List<T>.Sort(), egy InvalidOperationException kivételt dob.

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

A kivételt háromféleképpen szüntetheti meg:

  • Ha birtokolhatja a rendezni kívánt típust (vagyis ha a forráskódot te irányítod), módosíthatja a típust a IComparable<T> vagy a IComparable felület implementálásához. Ehhez implementálnia kell vagy a IComparable<T>.CompareTo, vagy a CompareTo metódust. Az illesztő implementáció hozzáadása egy meglévő típushoz nem jelent kompatibilitástörő változást.

    Az alábbi példa ezt a megközelítést használja a IComparable<T> osztály Person implementációjának biztosítására. Továbbra is meghívhatja a gyűjtemény vagy a tömb általános rendezési módszerét, és ahogy a példában látható kimenet mutatja, a gyűjtemény rendezése sikeresen megtörtént.

    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
    
  • Ha nem tudja módosítani a rendezni kívánt típus forráskódját, meghatározhat egy speciális célú rendezési osztályt, amely megvalósítja a IComparer<T> felületet. Meghívhatja a Sort metódus egy túlterhelését, amely tartalmazza a IComparer<T> paramétert. Ez a megközelítés különösen akkor hasznos, ha olyan speciális rendezési osztályt szeretne létrehozni, amely több feltétel alapján rendezheti az objektumokat.

    Az alábbi példa egy egyéni PersonComparer osztály fejlesztését alkalmazza, amelyet a Person gyűjtemények rendezésére használnak. Ezután átadja az osztály egy példányát a List<T>.Sort(IComparer<T>) metódusnak.

    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
    
  • Ha nem tudja módosítani a rendezni kívánt típus forráskódját, létrehozhat egy meghatalmazottat Comparison<T> a rendezés végrehajtásához. A meghatalmazott aláírása

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

    Az alábbi példa a PersonComparison delegált aláírásának megfelelő metódust definiálva alkalmazza a Comparison<T> megközelítést. Ezután átadja ezt a delegáltat a List<T>.Sort(Comparison<T>) metódusnak.

    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
    

Null értékű<T> értékének megadása a mögöttes típusra

A mögöttes típushoz tartozó érték leadásának Nullable<T> megkísérlése kivételt null okoz, és a következő hibaüzenetet jeleníti meg: "InvalidOperationException

Az alábbi példa kivételt InvalidOperationException jelez, ha egy értéket tartalmazó Nullable(Of Integer) tömb iterálását kísérli meg.

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

A kivétel megakadályozása:

Az alábbi példa mindkettőt megteszi a InvalidOperationException kivétel elkerülése érdekében.

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

System.Linq.Enumerable metódus meghívása üres gyűjteményen

A Enumerable.Aggregate, Enumerable.Average, Enumerable.First, Enumerable.Last, Enumerable.Max, Enumerable.MinEnumerable.Singleés Enumerable.SingleOrDefault metódusok műveleteket hajtanak végre egy sorozaton, és egyetlen eredményt ad vissza. A metódusok egyes túlterhelései kivételt InvalidOperationException képeznek, ha a sorozat üres, míg más túlterhelések visszatérnek null. A Enumerable.SingleOrDefault metódus kivételt InvalidOperationException is jelez, ha a sorozat több elemet is tartalmaz.

Megjegyzés

A InvalidOperationException kivételt dobó metódusok többsége túlterhelés. Győződjön meg arról, hogy tisztában van a választott túlterhelés viselkedésével.

Az alábbi táblázat felsorolja az egyes InvalidOperationException metódusok hívásai által küldött kivételobjektumok kivételüzeneteitSystem.Linq.Enumerable.

Metódus Üzenet
Aggregate
Average
Last
Max
Min
A sorozat nem tartalmaz elemeket
First A sorozat nem tartalmaz egyező elemet
Single
SingleOrDefault
A sorozat több egyező elemet tartalmaz

A kivétel megszüntetésének vagy kezelésének módja az alkalmazás feltételezéseitől és a hívott módszertől függ.

A példák további részleteket nyújtanak.

Az alábbi példa egy 4-nél nagyobb értékeket eredményező sorozat átlagának kiszámítására használja a Enumerable.Average metódust. Mivel az eredeti tömb egyik értéke sem haladja meg a 4-et, a sorozat nem tartalmaz értékeket, és a metódus kivételt InvalidOperationException dob.

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

A kivétel kiküszöbölhető a Any metódus meghívásával annak megállapításához, hogy a sorozat tartalmaz-e elemeket, mielőtt meghívja a sorozatot feldolgozó metódust, ahogyan az az alábbi példában is látható.

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.

A Enumerable.First metódus egy sorozat első elemét vagy egy adott feltételnek megfelelő sorozat első elemét adja vissza. Ha a sorozat üres, és ezért nincs első eleme, kivételt InvalidOperationException okoz.

A következő példában a Enumerable.First<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>) metódus kivételt InvalidOperationException jelez, mert a dbQueryResults tömb nem tartalmaz 4-nél nagyobb elemet.

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

Meghívhatja a Enumerable.FirstOrDefault metódust Enumerable.First helyett, hogy egy megadott vagy alapértelmezett értéket adjon vissza. Ha a metódus nem talál egy első elemet a sorozatban, az adott adattípus alapértelmezett értékét adja vissza. Az alapértelmezett érték null egy referenciatípus esetén, nulla egy numerikus adattípus esetén, és DateTime.MinValue a DateTime típus esetén.

Megjegyzés

A metódus által Enumerable.FirstOrDefault visszaadott érték értelmezését gyakran bonyolítja az a tény, hogy a típus alapértelmezett értéke érvényes érték lehet a sorozatban. Ebben az esetben meghívja a Enumerable.Any metódust annak megállapításához, hogy a sorozatnak vannak-e érvényes tagjai a metódus meghívása Enumerable.First előtt.

Az alábbi példa meghívja a metódust, Enumerable.FirstOrDefault<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>) hogy megakadályozza az InvalidOperationException előző példában szereplő kivételt.

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.

Hívd meg az Enumerable.Single vagy az Enumerable.SingleOrDefault metódust egy olyan sorozaton, amelynek nincs eleme.

A Enumerable.Single metódus egy sorozat egyetlen elemét adja vissza, vagy egy adott feltételnek megfelelő sorozat egyetlen elemét. Ha nincsenek elemek a sorozatban, vagy ha egynél több elem van, a metódus kivételt InvalidOperationException jelez.

A metódussal Enumerable.SingleOrDefault egy alapértelmezett értéket adhat vissza ahelyett, hogy kivételt eredményez, ha a sorozat nem tartalmaz elemeket. Azonban a Enumerable.SingleOrDefault metódus továbbra is egy InvalidOperationException kivételt dob, ha a sorozat több elemet tartalmaz.

Az alábbi táblázat felsorolja a InvalidOperationException kivételobjektumok kivételüzeneteit, amelyeket a Enumerable.Single és Enumerable.SingleOrDefault metódusok hívásai indítottak.

Metódus Üzenet
Single A sorozat nem tartalmaz egyező elemet
Single
SingleOrDefault
A sorozat több egyező elemet tartalmaz

A következő példában a Enumerable.Single metódus hívása kivételt InvalidOperationException eredményez, mert a sorozatnak nincs 4-nél nagyobb eleme.

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

Az alábbi példa a InvalidOperationException kivétel megakadályozására törekszik, amely akkor dobódik, ha a sorozat üres, helyette a Enumerable.SingleOrDefault metódus meghívásával. Mivel azonban ez a sorozat több olyan elemet ad vissza, amelyek értéke nagyobb, mint 2, kivételt InvalidOperationException is eredményez.

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

A metódus meghívása Enumerable.Single feltételezi, hogy egy sorozat vagy a megadott feltételeknek megfelelő sorozat csak egy elemet tartalmaz. Enumerable.SingleOrDefault nullával vagy egy eredménnyel rendelkező sorozatot feltételez, de nincs több. Ha ez a feltételezés szándékos az Ön részéről, és ezek a feltételek nem teljesülnek, az eredményként kapott InvalidOperationException újbóli dobása vagy elkapása megfelelő. Ellenkező esetben, vagy ha arra számít, hogy bizonyos gyakorisággal érvénytelen feltételek lépnek fel, érdemes megfontolnia valamilyen más Enumerable módszernek a használatát, mint például FirstOrDefault vagy Where.

Dinamikus alkalmazásközi tartományhozzáférés

A OpCodes.Ldflda közös köztes nyelv (CIL) utasítás kivételt InvalidOperationException jelent, ha a lekérni kívánt mezőt tartalmazó objektum nem abban az alkalmazástartományban található, amelyben a kód végrehajtása történik. Egy mező címe csak abból az alkalmazástartományból érhető el, amelyben található.

InvalidOperationException kivétel elvetése

Kivételt InvalidOperationException csak akkor szabad kivenni, ha az objektum állapota valamilyen okból nem támogatja az adott metódushívást. Ez azt jelzi, hogy a metódushívás bizonyos körülmények között vagy kontextusban érvényes, más esetekben azonban érvénytelen.

Ha a metódushívási hiba oka érvénytelen argumentum, akkor ArgumentException vagy annak egyik származtatott osztályát, ArgumentNullException vagy ArgumentOutOfRangeExceptiona metódust kell dobni helyette.