Bagikan melalui


Kelas System.InvalidOperationException

Artikel ini menyediakan keterangan tambahan untuk dokumentasi referensi untuk API ini.

InvalidOperationException digunakan dalam kasus ketika kegagalan untuk memanggil metode disebabkan oleh alasan selain argumen yang tidak valid. Biasanya, itu dilemparkan ketika status objek tidak dapat mendukung panggilan metode. Misalnya, InvalidOperationException pengecualian dilemparkan oleh metode seperti:

Penting

InvalidOperationException Karena pengecualian dapat dilemparkan dalam berbagai keadaan, penting untuk membaca pesan pengecualian yang dikembalikan oleh Message properti.

InvalidOperationException menggunakan HRESULT COR_E_INVALIDOPERATION, yang memiliki nilai 0x80131509.

Untuk daftar nilai properti awal untuk instans InvalidOperationException, lihat InvalidOperationException konstruktor.

Penyebab umum pengecualian InvalidOperationException

Bagian berikut menunjukkan bagaimana beberapa kasus umum di mana dalam InvalidOperationException pengecualian dilemparkan dalam aplikasi. Cara Anda menangani masalah tergantung pada situasi tertentu. Namun, yang paling umum, pengecualian dihasilkan dari kesalahan pengembang, dan InvalidOperationException pengecualian dapat diantisipasi dan dihindari.

Memperbarui utas UI dari utas non-UI

Seringkali, utas pekerja digunakan untuk melakukan beberapa pekerjaan latar belakang yang melibatkan pengumpulan data untuk ditampilkan di antarmuka pengguna aplikasi. Akan tetapi. sebagian besar kerangka kerja aplikasi GUI (antarmuka pengguna grafis) untuk .NET, seperti Formulir Windows dan Windows Presentation Foundation (WPF), memungkinkan Anda mengakses objek GUI hanya dari utas yang membuat dan mengelola UI (utas Utama atau UI). InvalidOperationException Dilemparkan ketika Anda mencoba mengakses elemen UI dari utas selain utas UI. Teks pesan pengecualian diperlihatkan dalam tabel berikut.

Jenis Aplikasi Pesan
Aplikasi WPF Utas panggilan tidak dapat mengakses objek ini karena utas yang berbeda memilikinya.
Aplikasi UWP Aplikasi ini disebut antarmuka yang di-marshal untuk utas yang berbeda.
aplikasi Formulir Windows Operasi lintas alur tidak valid: Kontrol 'TextBox1' yang diakses dari utas selain utas tempat alur dibuat.

Kerangka kerja UI untuk .NET menerapkan pola dispatcher yang menyertakan metode untuk memeriksa apakah panggilan ke anggota elemen UI sedang dijalankan pada utas UI, dan metode lain untuk menjadwalkan panggilan pada utas UI:

  • Di aplikasi WPF, panggil Dispatcher.CheckAccess metode untuk menentukan apakah metode berjalan pada utas non-UI. Ini mengembalikan jika metode berjalan pada utas true UI dan false sebaliknya. Panggil salah satu kelebihan beban metode untuk menjadwalkan panggilan pada utas Dispatcher.Invoke UI.
  • Di aplikasi UWP, periksa CoreDispatcher.HasThreadAccess properti untuk menentukan apakah metode berjalan pada utas non-UI. CoreDispatcher.RunAsync Panggil metode untuk menjalankan delegasi yang memperbarui utas UI.
  • Di aplikasi Formulir Windows, gunakan Control.InvokeRequired properti untuk menentukan apakah metode berjalan pada utas non-UI. Panggil salah satu kelebihan beban metode untuk menjalankan delegasi yang memperbarui utas Control.Invoke UI.

Contoh berikut mengilustrasikan InvalidOperationException pengecualian yang dilemparkan saat Anda mencoba memperbarui elemen UI dari utas selain utas yang membuatnya. Setiap contoh mengharuskan Anda membuat dua kontrol:

  • Kontrol kotak teks bernama textBox1. Dalam aplikasi Formulir Windows, Anda harus mengatur propertinya Multiline ke true.
  • Kontrol tombol bernama threadExampleBtn. Contoh ini menyediakan handler, ThreadsExampleBtn_Click, untuk peristiwa tombol Click .

Dalam setiap kasus, penanganan threadExampleBtn_Click aktivitas memanggil DoSomeWork metode dua kali. Panggilan pertama berjalan secara sinkron dan berhasil. Tetapi panggilan kedua, karena berjalan secara asinkron pada utas kumpulan utas, mencoba memperbarui UI dari utas non-UI. Ini menghasilkan InvalidOperationException pengecualian.

Aplikasi WPF

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

Versi DoSomeWork metode berikut menghilangkan pengecualian dalam aplikasi WPF.

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

Aplikasi Windows Forms

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

Versi DoSomeWork metode berikut menghilangkan pengecualian dalam aplikasi Formulir Windows.

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

Mengubah koleksi saat melakukan iterasi

Pernyataan foreach dalam C#, for...in dalam F#, atau For Each pernyataan di Visual Basic digunakan untuk melakukan iterasi anggota koleksi dan untuk membaca atau memodifikasi elemen individualnya. Namun, ini tidak dapat digunakan untuk menambahkan atau menghapus item dari koleksi. Melakukan ini melemparkan InvalidOperationException pengecualian dengan pesan yang mirip dengan, "Koleksi telah dimodifikasi; operasi enumerasi mungkin tidak dijalankan."

Contoh berikut mengurai kumpulan bilangan bulat yang mencoba menambahkan kuadrat dari setiap bilangan bulat ke koleksi. Contohnya melempar InvalidOperationException dengan panggilan pertama ke List<T>.Add metode .

using System;
using System.Collections.Generic;

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

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

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

Module Example6
    Public Sub Main()
        Dim numbers As New List(Of Integer)({1, 2, 3, 4, 5})
        For Each number In numbers
            Dim square As Integer = CInt(Math.Pow(number, 2))
            Console.WriteLine("{0}^{1}", number, square)
            Console.WriteLine("Adding {0} to the collection..." + vbCrLf,
                           square)
            numbers.Add(square)
        Next
    End Sub
End Module
' The example displays the following output:
'    1^1
'    Adding 1 to the collection...
'    
'    
'    Unhandled Exception: System.InvalidOperationException: Collection was modified; 
'       enumeration operation may not execute.
'       at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
'       at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
'       at Example.Main()

Anda dapat menghilangkan pengecualian dengan salah satu dari dua cara, tergantung pada logika aplikasi Anda:

  • Jika elemen harus ditambahkan ke koleksi saat melakukan iterasi, Anda dapat melakukan iterasi dengan indeks menggunakan for pernyataan (for..to dalam F#) alih-alih foreach, , for...inatau For Each. Contoh berikut menggunakan pernyataan untuk menambahkan kuadrat angka dalam koleksi ke koleksi.

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

    Perhatikan bahwa Anda harus menetapkan jumlah iterasi sebelum melakukan iterasi koleksi baik dengan menggunakan penghitung di dalam perulangan yang akan keluar dari perulangan dengan tepat, dengan mengulang mundur, dari Count - 1 hingga 0, atau, seperti contohnya, dengan menetapkan jumlah elemen dalam array ke variabel dan menggunakannya untuk membuat batas atas perulangan. Jika tidak, jika elemen ditambahkan ke koleksi pada setiap iterasi, hasil perulangan tanpa akhir.

  • Jika tidak perlu menambahkan elemen ke koleksi saat melakukan iterasi, Anda dapat menyimpan elemen yang akan ditambahkan dalam koleksi sementara yang Anda tambahkan saat iterasi koleksi selesai. Contoh berikut menggunakan pendekatan ini untuk menambahkan kuadrat angka dalam koleksi ke koleksi sementara, lalu untuk menggabungkan koleksi ke dalam satu objek array.

    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
    

Mengurutkan array atau koleksi yang objeknya tidak dapat dibandingkan

Metode pengurutan tujuan umum, seperti Array.Sort(Array) metode atau List<T>.Sort() metode , biasanya mengharuskan setidaknya salah satu objek diurutkan mengimplementasikan IComparable<T> atau IComparable antarmuka. Jika tidak, koleksi atau array tidak dapat diurutkan, dan metode melemparkan InvalidOperationException pengecualian. Contoh berikut mendefinisikan Person kelas, menyimpan dua Person objek dalam objek generik List<T> , dan mencoba mengurutkannya. Seperti yang ditunjukkan oleh output dari contoh, panggilan ke List<T>.Sort() metode melempar InvalidOperationException.

using System;
using System.Collections.Generic;

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

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

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

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

let people = ResizeArray()

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

Public Class Person9
    Public Sub New(fName As String, lName As String)
        FirstName = fName
        LastName = lName
    End Sub

    Public Property FirstName As String
    Public Property LastName As String
End Class

Module Example9
    Public Sub Main()
        Dim people As New List(Of Person9)()

        people.Add(New Person9("John", "Doe"))
        people.Add(New Person9("Jane", "Doe"))
        people.Sort()
        For Each person In people
            Console.WriteLine("{0} {1}", person.FirstName, person.LastName)
        Next
    End Sub
End Module
' The example displays the following output:
'    Unhandled Exception: System.InvalidOperationException: Failed to compare two elements in the array. ---> 
'       System.ArgumentException: At least one object must implement IComparable.
'       at System.Collections.Comparer.Compare(Object a, Object b)
'       at System.Collections.Generic.ArraySortHelper`1.SwapIfGreater(T[] keys, IComparer`1 comparer, Int32 a, Int32 b)
'       at System.Collections.Generic.ArraySortHelper`1.DepthLimitedQuickSort(T[] keys, Int32 left, Int32 right, IComparer`1 comparer, Int32 depthLimit)
'       at System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index, Int32 length, IComparer`1 comparer)
'       --- End of inner exception stack trace ---
'       at System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index, Int32 length, IComparer`1 comparer)
'       at System.Array.Sort[T](T[] array, Int32 index, Int32 length, IComparer`1 comparer)
'       at System.Collections.Generic.List`1.Sort(Int32 index, Int32 count, IComparer`1 comparer)
'       at Example.Main()

Anda dapat menghilangkan pengecualian dengan salah satu dari tiga cara:

  • Jika Anda dapat memiliki jenis yang Anda coba urutkan (yaitu, jika Anda mengontrol kode sumbernya), Anda dapat memodifikasinya untuk mengimplementasikan IComparable<T> antarmuka atau IComparable . Ini mengharuskan Anda menerapkan IComparable<T>.CompareTo metode atau CompareTo . Menambahkan implementasi antarmuka ke jenis yang ada bukanlah perubahan yang melanggar.

    Contoh berikut menggunakan pendekatan ini untuk memberikan IComparable<T> implementasi untuk Person kelas. Anda masih dapat memanggil metode pengurutan umum koleksi atau array dan, seperti yang ditunjukkan output dari contoh, pengurutan koleksi berhasil.

    using System;
    using System.Collections.Generic;
    
    public class Person2 : IComparable<Person>
    {
        public Person2(String fName, String lName)
        {
            FirstName = fName;
            LastName = lName;
        }
    
        public String FirstName { get; set; }
        public String LastName { get; set; }
    
        public int CompareTo(Person other)
        {
            return String.Format("{0} {1}", LastName, FirstName).
                   CompareTo(String.Format("{0} {1}", other.LastName, other.FirstName));
        }
    }
    
    public class ListSortEx2
    {
        public static void Main()
        {
            var people = new List<Person2>();
    
            people.Add(new Person2("John", "Doe"));
            people.Add(new Person2("Jane", "Doe"));
            people.Sort();
            foreach (var person in people)
                Console.WriteLine("{0} {1}", person.FirstName, person.LastName);
        }
    }
    // The example displays the following output:
    //       Jane Doe
    //       John Doe
    
    open System
    
    type Person(firstName: string, lastName: string) =
        member val FirstName = firstName with get, set
        member val LastName = lastName with get, set
        
        interface IComparable<Person> with
            member this.CompareTo(other) =
                compare $"{this.LastName} {this.FirstName}" $"{other.LastName} {other.FirstName}"
    
    let people = ResizeArray()
    
    people.Add(new Person("John", "Doe"))
    people.Add(new Person("Jane", "Doe"))
    people.Sort()
    for person in people do
        printfn $"{person.FirstName} {person.LastName}"
    // The example displays the following output:
    //       Jane Doe
    //       John Doe
    
    Imports System.Collections.Generic
    
    Public Class Person : Implements IComparable(Of Person)
       Public Sub New(fName As String, lName As String)
          FirstName = fName
          LastName = lName
       End Sub
       
       Public Property FirstName As String
       Public Property LastName As String
       
       Public Function CompareTo(other As Person) As Integer _
              Implements IComparable(Of Person).CompareTo
          Return String.Format("{0} {1}", LastName, FirstName).
                CompareTo(String.Format("{0} {1}", other.LastName, other.FirstName))    
       End Function
    End Class
    
    Module Example10
        Public Sub Main()
            Dim people As New List(Of Person)()
    
            people.Add(New Person("John", "Doe"))
            people.Add(New Person("Jane", "Doe"))
            people.Sort()
            For Each person In people
                Console.WriteLine("{0} {1}", person.FirstName, person.LastName)
            Next
        End Sub
    End Module
    ' The example displays the following output:
    '       Jane Doe
    '       John Doe
    
  • Jika Anda tidak dapat mengubah kode sumber untuk jenis yang Anda coba urutkan, Anda dapat menentukan kelas pengurutan tujuan khusus yang mengimplementasikan IComparer<T> antarmuka. Anda dapat memanggil kelebihan beban Sort metode yang menyertakan IComparer<T> parameter. Pendekatan ini sangat berguna jika Anda ingin mengembangkan kelas pengurutan khusus yang dapat mengurutkan objek berdasarkan beberapa kriteria.

    Contoh berikut menggunakan pendekatan dengan mengembangkan kelas kustom PersonComparer yang digunakan untuk mengurutkan Person koleksi. Kemudian meneruskan instans kelas ini ke List<T>.Sort(IComparer<T>) metode .

    using System;
    using System.Collections.Generic;
    
    public class Person3
    {
        public Person3(String fName, String lName)
        {
            FirstName = fName;
            LastName = lName;
        }
    
        public String FirstName { get; set; }
        public String LastName { get; set; }
    }
    
    public class PersonComparer : IComparer<Person3>
    {
        public int Compare(Person3 x, Person3 y)
        {
            return String.Format("{0} {1}", x.LastName, x.FirstName).
                   CompareTo(String.Format("{0} {1}", y.LastName, y.FirstName));
        }
    }
    
    public class ListSortEx3
    {
        public static void Main()
        {
            var people = new List<Person3>();
    
            people.Add(new Person3("John", "Doe"));
            people.Add(new Person3("Jane", "Doe"));
            people.Sort(new PersonComparer());
            foreach (var person in people)
                Console.WriteLine("{0} {1}", person.FirstName, person.LastName);
        }
    }
    // The example displays the following output:
    //       Jane Doe
    //       John Doe
    
    open System
    open System.Collections.Generic
    
    type Person(firstName, lastName) =
        member val FirstName = firstName with get, set
        member val LastName = lastName with get, set
    
    type PersonComparer() =
        interface IComparer<Person> with
            member _.Compare(x: Person, y: Person) =
                $"{x.LastName} {x.FirstName}".CompareTo $"{y.LastName} {y.FirstName}"
    
    let people = ResizeArray()
    
    people.Add(Person("John", "Doe"))
    people.Add(Person("Jane", "Doe"))
    people.Sort(PersonComparer())
    for person in people do
        printfn $"{person.FirstName} {person.LastName}"
    // The example displays the following output:
    //       Jane Doe
    //       John Doe
    
    Imports System.Collections.Generic
    
    Public Class Person11
        Public Sub New(fName As String, lName As String)
            FirstName = fName
            LastName = lName
        End Sub
    
        Public Property FirstName As String
        Public Property LastName As String
    End Class
    
    Public Class PersonComparer : Implements IComparer(Of Person11)
        Public Function Compare(x As Person11, y As Person11) As Integer _
              Implements IComparer(Of Person11).Compare
            Return String.Format("{0} {1}", x.LastName, x.FirstName).
                 CompareTo(String.Format("{0} {1}", y.LastName, y.FirstName))
        End Function
    End Class
    
    Module Example11
        Public Sub Main()
            Dim people As New List(Of Person11)()
    
            people.Add(New Person11("John", "Doe"))
            people.Add(New Person11("Jane", "Doe"))
            people.Sort(New PersonComparer())
            For Each person In people
                Console.WriteLine("{0} {1}", person.FirstName, person.LastName)
            Next
        End Sub
    End Module
    ' The example displays the following output:
    '       Jane Doe
    '       John Doe
    
  • Jika Anda tidak dapat mengubah kode sumber untuk jenis yang anda coba urutkan, Anda bisa membuat Comparison<T> delegasi untuk melakukan pengurutan. Tanda tangan delegasi adalah

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

    Contoh berikut menggunakan pendekatan dengan menentukan PersonComparison metode yang cocok dengan Comparison<T> tanda tangan delegasi. Kemudian meneruskan delegasi ini ke List<T>.Sort(Comparison<T>) metode .

    using System;
    using System.Collections.Generic;
    
    public class Person
    {
       public Person(String fName, String lName)
       {
          FirstName = fName;
          LastName = lName;
       }
    
       public String FirstName { get; set; }
       public String LastName { get; set; }
    }
    
    public class ListSortEx4
    {
       public static void Main()
       {
          var people = new List<Person>();
    
          people.Add(new Person("John", "Doe"));
          people.Add(new Person("Jane", "Doe"));
          people.Sort(PersonComparison);
          foreach (var person in people)
             Console.WriteLine("{0} {1}", person.FirstName, person.LastName);
       }
    
       public static int PersonComparison(Person x, Person y)
       {
          return String.Format("{0} {1}", x.LastName, x.FirstName).
                 CompareTo(String.Format("{0} {1}", y.LastName, y.FirstName));
       }
    }
    // The example displays the following output:
    //       Jane Doe
    //       John Doe
    
    open System
    open System.Collections.Generic
    
    type Person(firstName, lastName) =
        member val FirstName = firstName with get, set
        member val LastName = lastName with get, set
    
    let personComparison (x: Person) (y: Person) =
        $"{x.LastName} {x.FirstName}".CompareTo $"{y.LastName} {y.FirstName}"
    
    let people = ResizeArray()
    
    people.Add(Person("John", "Doe"))
    people.Add(Person("Jane", "Doe"))
    people.Sort personComparison
    for person in people do
        printfn $"{person.FirstName} {person.LastName}"
    
    // The example displays the following output:
    //       Jane Doe
    //       John Doe
    
    Imports System.Collections.Generic
    
    Public Class Person12
        Public Sub New(fName As String, lName As String)
            FirstName = fName
            LastName = lName
        End Sub
    
        Public Property FirstName As String
        Public Property LastName As String
    End Class
    
    Module Example12
        Public Sub Main()
            Dim people As New List(Of Person12)()
    
            people.Add(New Person12("John", "Doe"))
            people.Add(New Person12("Jane", "Doe"))
            people.Sort(AddressOf PersonComparison)
            For Each person In people
                Console.WriteLine("{0} {1}", person.FirstName, person.LastName)
            Next
        End Sub
    
        Public Function PersonComparison(x As Person12, y As Person12) As Integer
            Return String.Format("{0} {1}", x.LastName, x.FirstName).
                 CompareTo(String.Format("{0} {1}", y.LastName, y.FirstName))
        End Function
    End Module
    ' The example displays the following output:
    '       Jane Doe
    '       John Doe
    

Transmisi T> Nullable<yang null ke jenis yang mendasar

Mencoba untuk melemparkan Nullable<T> nilai yang null ke jenis yang mendasar InvalidOperationException memunculkan pengecualian dan menampilkan pesan kesalahan, "Objek nullable harus memiliki nilai.

Contoh berikut melemparkan InvalidOperationException pengecualian saat mencoba melakukan iterasi array yang menyertakan Nullable(Of Integer) nilai.

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

Untuk mencegah pengecualian:

Contoh berikut melakukan keduanya untuk menghindari InvalidOperationException pengecualian.

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

Memanggil metode System.Linq.Enumerable pada koleksi kosong

Metode Enumerable.Aggregate, , Enumerable.FirstEnumerable.Average, Enumerable.LastEnumerable.Max, Enumerable.Min, Enumerable.Singledan Enumerable.SingleOrDefault melakukan operasi pada urutan dan mengembalikan satu hasil. Beberapa kelebihan beban metode ini melemparkan InvalidOperationException pengecualian ketika urutan kosong, sementara kelebihan beban lainnya mengembalikan null. Metode ini Enumerable.SingleOrDefault juga melemparkan InvalidOperationException pengecualian ketika urutan berisi lebih dari satu elemen.

Catatan

Sebagian besar metode yang melemparkan InvalidOperationException pengecualian adalah kelebihan beban. Pastikan Anda memahami perilaku kelebihan beban yang Anda pilih.

Tabel berikut mencantumkan pesan pengecualian dari objek pengecualian yang InvalidOperationException dilemparkan oleh panggilan ke beberapa System.Linq.Enumerable metode.

Metode Pesan
Aggregate
Average
Last
Max
Min
Urutan tidak berisi elemen
First Urutan tidak berisi elemen yang cocok
Single
SingleOrDefault
Urutan berisi lebih dari satu elemen yang cocok

Cara Anda menghilangkan atau menangani pengecualian tergantung pada asumsi aplikasi Anda dan pada metode tertentu yang Anda panggil.

Contohnya memberikan detail tambahan.

Contoh berikut menggunakan Enumerable.Average metode untuk menghitung rata-rata urutan yang nilainya lebih besar dari 4. Karena tidak ada nilai dari array asli yang melebihi 4, tidak ada nilai yang disertakan dalam urutan, dan metode melemparkan InvalidOperationException pengecualian.

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

Pengecualian dapat dihilangkan dengan memanggil Any metode untuk menentukan apakah urutan berisi elemen apa pun sebelum memanggil metode yang memproses urutan, seperti yang ditunjukkan contoh berikut.

using System;
using System.Linq;

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

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

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

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

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

Module Example1
    Public Sub Main()
        Dim dbQueryResults() As Integer = {1, 2, 3, 4}
        Dim moreThan4 = dbQueryResults.Where(Function(num) num > 4)

        If moreThan4.Any() Then
            Console.WriteLine("Average value of numbers greater than 4: {0}:",
                             moreThan4.Average())
        Else
            ' Handle empty collection. 
            Console.WriteLine("The dataset has no values greater than 4.")
        End If
    End Sub
End Module
' The example displays the following output:
'       The dataset has no values greater than 4.

Metode mengembalikan Enumerable.First item pertama secara berurutan atau elemen pertama dalam urutan yang memenuhi kondisi yang ditentukan. Jika urutannya kosong dan karenanya tidak memiliki elemen pertama, urutan tersebut akan melemparkan InvalidOperationException pengecualian.

Dalam contoh berikut, Enumerable.First<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>) metode melemparkan InvalidOperationException pengecualian karena array dbQueryResults tidak berisi elemen yang lebih besar dari 4.

using System;
using System.Linq;

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

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

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

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

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

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

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

Module Example2
    Public Sub Main()
        Dim dbQueryResults() As Integer = {1, 2, 3, 4}

        Dim firstNum = dbQueryResults.First(Function(n) n > 4)

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

Anda dapat memanggil metode alih-alih Enumerable.FirstOrDefaultEnumerable.First mengembalikan nilai yang ditentukan atau default. Jika metode tidak menemukan elemen pertama dalam urutan, metode mengembalikan nilai default untuk jenis data tersebut. Nilai default adalah null untuk jenis referensi, nol untuk jenis data numerik, dan DateTime.MinValue untuk jenisnya DateTime .

Catatan

Menginterpretasikan nilai yang dikembalikan oleh Enumerable.FirstOrDefault metode sering kali rumit oleh fakta bahwa nilai default jenis dapat menjadi nilai yang valid dalam urutan. Dalam hal ini, Anda memanggil Enumerable.Any metode untuk menentukan apakah urutan memiliki anggota yang valid sebelum memanggil Enumerable.First metode .

Contoh berikut memanggil Enumerable.FirstOrDefault<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>) metode untuk mencegah pengecualian yang InvalidOperationException dilemparkan dalam contoh sebelumnya.

using System;
using System.Linq;

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

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

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

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

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

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

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

Module Example3
    Public Sub Main()
        Dim dbQueryResults() As Integer = {1, 2, 3, 4}

        Dim firstNum = dbQueryResults.FirstOrDefault(Function(n) n > 4)

        If firstNum = 0 Then
            Console.WriteLine("No value is greater than 4.")
        Else
            Console.WriteLine("The first value greater than 4 is {0}",
                           firstNum)
        End If
    End Sub
End Module
' The example displays the following output:
'       No value is greater than 4.

Panggil Enumerable.Single atau Enumerable.SingleOrDefault pada urutan tanpa satu elemen

Metode mengembalikan Enumerable.Single satu-satunya elemen urutan, atau satu-satunya elemen urutan yang memenuhi kondisi tertentu. Jika tidak ada elemen dalam urutan, atau jika ada lebih dari satu elemen , metode melemparkan InvalidOperationException pengecualian.

Anda dapat menggunakan Enumerable.SingleOrDefault metode untuk mengembalikan nilai default alih-alih melemparkan pengecualian ketika urutan tidak berisi elemen. Namun, metode ini Enumerable.SingleOrDefault masih melemparkan InvalidOperationException pengecualian ketika urutannya berisi lebih dari satu elemen.

Tabel berikut mencantumkan pesan pengecualian dari InvalidOperationException objek pengecualian yang dilemparkan oleh panggilan ke Enumerable.Single metode dan Enumerable.SingleOrDefault .

Metode Pesan
Single Urutan tidak berisi elemen yang cocok
Single
SingleOrDefault
Urutan berisi lebih dari satu elemen yang cocok

Dalam contoh berikut, panggilan ke Enumerable.Single metode melemparkan InvalidOperationException pengecualian karena urutannya tidak memiliki elemen yang lebih besar dari 4.

using System;
using System.Linq;

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

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

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

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

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

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

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

Module Example4
    Public Sub Main()
        Dim dbQueryResults() As Integer = {1, 2, 3, 4}

        Dim singleObject = dbQueryResults.Single(Function(value) value > 4)

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

Contoh berikut mencoba mencegah pengecualian yang InvalidOperationException dilemparkan ketika urutan kosong dengan memanggil Enumerable.SingleOrDefault metode . Namun, karena urutan ini mengembalikan beberapa elemen yang nilainya lebih besar dari 2, urutan ini juga melemparkan InvalidOperationException pengecualian.

using System;
using System.Linq;

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

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

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

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

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

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

Module Example5
    Public Sub Main()
        Dim dbQueryResults() As Integer = {1, 2, 3, 4}

        Dim singleObject = dbQueryResults.SingleOrDefault(Function(value) value > 2)

        If singleObject <> 0 Then
            Console.WriteLine("{0} is the only value greater than 2",
                             singleObject)
        Else
            ' Handle an empty collection.
            Console.WriteLine("No value is greater than 2")
        End If
    End Sub
End Module
' The example displays the following output:
'    Unhandled Exception: System.InvalidOperationException: 
'       Sequence contains more than one matching element
'       at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source, Func`2 predicate)
'       at Example.Main()

Memanggil Enumerable.Single metode mengasumsikan bahwa urutan atau urutan yang memenuhi kriteria yang ditentukan hanya berisi satu elemen. Enumerable.SingleOrDefault mengasumsikan urutan dengan nol atau satu hasil, tetapi tidak lebih. Jika asumsi ini adalah yang disederhanakan di bagian Anda dan kondisi ini tidak terpenuhi, menggulung balik atau menangkap hasilnya InvalidOperationException sesuai. Jika tidak, atau jika Anda mengharapkan bahwa kondisi yang tidak valid akan terjadi dengan beberapa frekuensi, Anda harus mempertimbangkan untuk menggunakan beberapa metode lain Enumerable , seperti FirstOrDefault atau Where.

Akses bidang domain lintas aplikasi dinamis

Instruksi OpCodes.Ldflda bahasa perantara umum (CIL) melemparkan InvalidOperationException pengecualian jika objek yang berisi bidang yang alamatnya Anda coba ambil tidak berada dalam domain aplikasi tempat kode Anda dijalankan. Alamat bidang hanya dapat diakses dari domain aplikasi tempat bidang berada.

Melempar pengecualian InvalidOperationException

Anda harus melemparkan InvalidOperationException pengecualian hanya ketika status objek Anda karena alasan tertentu tidak mendukung panggilan metode tertentu. Artinya, panggilan metode valid dalam beberapa keadaan atau konteks, tetapi tidak valid di orang lain.

Jika kegagalan pemanggilan metode disebabkan oleh argumen yang tidak valid, maka ArgumentException atau salah satu kelas turunannya, ArgumentNullException atau ArgumentOutOfRangeException, harus dilemparkan sebagai gantinya.