Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
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, metode seperti InvalidOperationException melemparkan pengecualian:
- IEnumerator.MoveNext jika objek koleksi dimodifikasi setelah enumerator dibuat. Untuk informasi selengkapnya, lihat Mengubah koleksi saat melakukan iterasi.
- ResourceSet.GetString jika set sumber daya ditutup sebelum panggilan metode dilakukan.
- XContainer.Add, jika objek atau objek yang akan ditambahkan akan menghasilkan dokumen XML yang salah terstruktur.
- Metode yang mencoba memanipulasi UI dari utas yang bukan utas utama atau utas UI.
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 instance InvalidOperationException, silakan lihat konstruktor InvalidOperationException.
Penyebab umum pengecualian InvalidOperationException
Bagian berikut menunjukkan bagaimana beberapa kasus umum di mana pengecualian InvalidOperationException 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 pekerjaan latar yang melibatkan pengumpulan data agar dapat ditampilkan di antarmuka pengguna aplikasi. Akan tetapi. sebagian besar kerangka kerja aplikasi GUI (antarmuka pengguna grafis) untuk .NET, seperti Windows Forms 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 memanggil antarmuka yang ditransfer ke utas yang berbeda. |
| Aplikasi Windows Forms | Operasi lintas thread tidak valid: Kontrol 'TextBox1' diakses dari thread selain thread tempat thread itu 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
truejika metode berjalan pada utas UI, danfalsejika tidak. 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. Panggil metode CoreDispatcher.RunAsync untuk menjalankan delegate yang memperbarui utas UI.
- Di aplikasi Windows Forms, gunakan Control.InvokeRequired properti untuk menentukan apakah metode berjalan pada utas non-UI. Panggil salah satu overload metode Control.Invoke untuk menjalankan delegasi yang memperbarui utas UI.
Contoh berikut menunjukkan pengecualian InvalidOperationException yang dilemparkan ketika Anda mencoba memperbarui elemen UI dari utas yang berbeda dengan utas yang membuatnya. Setiap contoh mengharuskan Anda membuat dua kontrol:
- Kontrol kotak teks bernama
textBox1. Di aplikasi Windows Forms, Anda harus mengatur propertinya Multiline ketrue. - Kontrol tombol bernama
threadExampleBtn. Contoh ini menyediakan handler,ThreadsExampleBtn_Click, untuk peristiwa tombolClick.
Dalam setiap kasus, pengendali acara threadExampleBtn_Click memanggil metode DoSomeWork 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 Windows Forms.
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 memproses koleksi bilangan bulat dengan mengiterasi dan mencoba menambahkan kuadrat dari setiap bilangan bulat ke dalam koleksi. Contohnya melemparkan InvalidOperationException pada panggilan pertama ke metode List<T>.Add.
using System;
using System.Collections.Generic;
public class IteratingEx1
{
public static void Main()
{
var numbers = new List<int>() { 1, 2, 3, 4, 5 };
foreach (var number in numbers)
{
int square = (int)Math.Pow(number, 2);
Console.WriteLine($"{number}^{square}");
Console.WriteLine($"Adding {square} to the collection...");
Console.WriteLine();
numbers.Add(square);
}
}
}
// The example displays the following output:
// 1^1
// Adding 1 to the collection...
//
//
// Unhandled Exception: System.InvalidOperationException: Collection was modified;
// enumeration operation may not execute.
// at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
// at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
// at Example.Main()
open System
let numbers = ResizeArray [| 1; 2; 3; 4; 5 |]
for number in numbers do
let square = Math.Pow(number, 2) |> int
printfn $"{number}^{square}"
printfn $"Adding {square} to the collection...\n"
numbers.Add square
// The example displays the following output:
// 1^1
// Adding 1 to the collection...
//
//
// Unhandled Exception: System.InvalidOperationException: Collection was modified
// enumeration operation may not execute.
// at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
// at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
// at <StartupCode$fs>.main()
Imports System.Collections.Generic
Module Example6
Public Sub Main()
Dim numbers As New List(Of Integer)({1, 2, 3, 4, 5})
For Each number In numbers
Dim square As Integer = CInt(Math.Pow(number, 2))
Console.WriteLine("{0}^{1}", number, square)
Console.WriteLine("Adding {0} to the collection..." + vbCrLf,
square)
numbers.Add(square)
Next
End Sub
End Module
' The example displays the following output:
' 1^1
' Adding 1 to the collection...
'
'
' Unhandled Exception: System.InvalidOperationException: Collection was modified;
' enumeration operation may not execute.
' at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
' at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
' at Example.Main()
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
forpernyataan (for..todalam F#) alih-alihforeach, ,for...inatauFor Each. Contoh berikut menggunakan pernyataan 'for' untuk menambahkan kuadrat angka dalam koleksi ke dalam 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($"{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 25open 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 25Imports 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 25Perhatikan bahwa Anda harus menetapkan jumlah iterasi sebelum melakukan iterasi pada koleksi, baik dengan menggunakan penghitung di dalam perulangan yang akan menghentikan perulangan secara tepat, menghitung mundur dari
Count- 1 hingga 0, atau, seperti pada contoh, dengan menetapkan jumlah elemen dalam array ke sebuah variabel dan menggunakannya untuk menentukan batas atas perulangan. Jika tidak, jika elemen ditambahkan ke dalam koleksi pada setiap iterasi, ini akan mengakibatkan perulangan tanpa henti.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 25open 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 25Imports 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 akan menghasilkan 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 melemparkan InvalidOperationException.
using System;
using System.Collections.Generic;
public class Person1
{
public Person1(string fName, string lName)
{
FirstName = fName;
LastName = lName;
}
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class ListSortEx1
{
public static void Main()
{
var people = new List<Person1>();
people.Add(new Person1("John", "Doe"));
people.Add(new Person1("Jane", "Doe"));
people.Sort();
foreach (var person in people)
Console.WriteLine($"{person.FirstName} {person.LastName}");
}
}
// The example displays the following output:
// Unhandled Exception: System.InvalidOperationException: Failed to compare two elements in the array. --->
// System.ArgumentException: At least one object must implement IComparable.
// at System.Collections.Comparer.Compare(Object a, Object b)
// at System.Collections.Generic.ArraySortHelper`1.SwapIfGreater(T[] keys, IComparer`1 comparer, Int32 a, Int32 b)
// at System.Collections.Generic.ArraySortHelper`1.DepthLimitedQuickSort(T[] keys, Int32 left, Int32 right, IComparer`1 comparer, Int32 depthLimit)
// at System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index, Int32 length, IComparer`1 comparer)
// --- End of inner exception stack trace ---
// at System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index, Int32 length, IComparer`1 comparer)
// at System.Array.Sort[T](T[] array, Int32 index, Int32 length, IComparer`1 comparer)
// at System.Collections.Generic.List`1.Sort(Int32 index, Int32 count, IComparer`1 comparer)
// at Example.Main()
type Person(firstName: string, lastName: string) =
member val FirstName = firstName with get, set
member val LastName = lastName with get, set
let people = ResizeArray()
people.Add(Person("John", "Doe"))
people.Add(Person("Jane", "Doe"))
people.Sort()
for person in people do
printfn $"{person.FirstName} {person.LastName}"
// The example displays the following output:
// Unhandled Exception: System.InvalidOperationException: Failed to compare two elements in the array. --->
// System.ArgumentException: At least one object must implement IComparable.
// at System.Collections.Comparer.Compare(Object a, Object b)
// at System.Collections.Generic.ArraySortHelper`1.SwapIfGreater(T[] keys, IComparer`1 comparer, Int32 a, Int32 b)
// at System.Collections.Generic.ArraySortHelper`1.DepthLimitedQuickSort(T[] keys, Int32 left, Int32 right, IComparer`1 comparer, Int32 depthLimit)
// at System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index, Int32 length, IComparer`1 comparer)
// --- End of inner exception stack trace ---
// at System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index, Int32 length, IComparer`1 comparer)
// at System.Array.Sort[T](T[] array, Int32 index, Int32 length, IComparer`1 comparer)
// at System.Collections.Generic.List`1.Sort(Int32 index, Int32 count, IComparer`1 comparer)
// at <StartupCode$fs>.main()
Imports System.Collections.Generic
Public Class Person9
Public Sub New(fName As String, lName As String)
FirstName = fName
LastName = lName
End Sub
Public Property FirstName As String
Public Property LastName As String
End Class
Module Example9
Public Sub Main()
Dim people As New List(Of Person9)()
people.Add(New Person9("John", "Doe"))
people.Add(New Person9("Jane", "Doe"))
people.Sort()
For Each person In people
Console.WriteLine("{0} {1}", person.FirstName, person.LastName)
Next
End Sub
End Module
' The example displays the following output:
' Unhandled Exception: System.InvalidOperationException: Failed to compare two elements in the array. --->
' System.ArgumentException: At least one object must implement IComparable.
' at System.Collections.Comparer.Compare(Object a, Object b)
' at System.Collections.Generic.ArraySortHelper`1.SwapIfGreater(T[] keys, IComparer`1 comparer, Int32 a, Int32 b)
' at System.Collections.Generic.ArraySortHelper`1.DepthLimitedQuickSort(T[] keys, Int32 left, Int32 right, IComparer`1 comparer, Int32 depthLimit)
' at System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index, Int32 length, IComparer`1 comparer)
' --- End of inner exception stack trace ---
' at System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index, Int32 length, IComparer`1 comparer)
' at System.Array.Sort[T](T[] array, Int32 index, Int32 length, IComparer`1 comparer)
' at System.Collections.Generic.List`1.Sort(Int32 index, Int32 count, IComparer`1 comparer)
' at Example.Main()
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 metode IComparable<T>.CompareTo atau CompareTo. Menambahkan implementasi antarmuka ke jenis yang ada bukanlah perubahan yang merusak.
Contoh berikut menggunakan pendekatan ini untuk memberikan IComparable<T> implementasi untuk
Personkelas. Anda masih dapat memanggil metode pengurutan umum koleksi atau array dan, seperti yang ditunjukkan oleh hasil contoh, pengurutan pada 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($"{person.FirstName} {person.LastName}"); } } // The example displays the following output: // Jane Doe // John Doeopen 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 DoeImports 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 DoeJika 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 overload dari metode
Sortyang mencakup parameter IComparer<T>. 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
PersonCompareryang digunakan untuk mengurutkanPersonkoleksi. Kemudian meneruskan sebuah instans dari kelas ini ke metode List<T>.Sort(IComparer<T>).using System; using System.Collections.Generic; public class Person3 { public Person3(String fName, String lName) { FirstName = fName; LastName = lName; } public String FirstName { get; set; } public String LastName { get; set; } } public class PersonComparer : IComparer<Person3> { public int Compare(Person3 x, Person3 y) { return String.Format("{0} {1}", x.LastName, x.FirstName). CompareTo(String.Format("{0} {1}", y.LastName, y.FirstName)); } } public class ListSortEx3 { public static void Main() { var people = new List<Person3>(); people.Add(new Person3("John", "Doe")); people.Add(new Person3("Jane", "Doe")); people.Sort(new PersonComparer()); foreach (var person in people) Console.WriteLine($"{person.FirstName} {person.LastName}"); } } // The example displays the following output: // Jane Doe // John Doeopen 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 DoeImports 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 DoeJika 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 Integerint Comparison<T>(T x, T y)Contoh berikut menggunakan pendekatan dengan menentukan metode
PersonComparisonyang sesuai dengan signature delegasi Comparison<T>. Kemudian meneruskan delegasi ini ke metode List<T>.Sort(Comparison<T>).using System; using System.Collections.Generic; public class Person { public Person(String fName, String lName) { FirstName = fName; LastName = lName; } public String FirstName { get; set; } public String LastName { get; set; } } public class ListSortEx4 { public static void Main() { var people = new List<Person>(); people.Add(new Person("John", "Doe")); people.Add(new Person("Jane", "Doe")); people.Sort(PersonComparison); foreach (var person in people) Console.WriteLine($"{person.FirstName} {person.LastName}"); } public static int PersonComparison(Person x, Person y) { return String.Format("{0} {1}", x.LastName, x.FirstName). CompareTo(String.Format("{0} {1}", y.LastName, y.FirstName)); } } // The example displays the following output: // Jane Doe // John Doeopen 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 DoeImports 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
Konversi Nullable<T> yang null ke tipe dasarnya
Mencoba untuk mengonversi nilai Nullable<T> yang null ke tipe dasarnya menghasilkan pengecualian InvalidOperationException 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:
-
Nullable<T>.HasValue Gunakan properti untuk memilih hanya elemen yang bukan
null. - Panggil salah satu Nullable<T>.GetValueOrDefault overload untuk memberikan nilai default untuk
null.
Contoh berikut melakukan kedua hal untuk menghindari kesalahan InvalidOperationException.
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.AverageEnumerable.First, 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 Enumerable.SingleOrDefault juga memicu pengecualian InvalidOperationException ketika urutan berisi lebih dari satu elemen.
Nota
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 InvalidOperationException yang dilemparkan oleh beberapa metode System.Linq.Enumerable.
| 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.
Ketika Anda sengaja memanggil salah satu metode ini tanpa memeriksa urutan kosong, Anda berasumsi bahwa urutannya tidak kosong, dan bahwa urutan kosong adalah kejadian yang tidak terduga. Dalam hal ini, menangkap atau melemparkan kembali pengecualian tersebut adalah tindakan yang tepat.
Jika Anda tidak sengaja gagal memeriksa urutan kosong, Anda dapat memanggil salah satu overload Enumerable.Any untuk menentukan apakah urutan tersebut berisi elemen apa pun.
Petunjuk / Saran
Memanggil Enumerable.Any<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>) metode sebelum menghasilkan urutan dapat meningkatkan performa jika data yang akan diproses mungkin berisi sejumlah besar elemen atau jika operasi yang menghasilkan urutan mahal.
Jika Anda telah memanggil metode seperti Enumerable.First, , Enumerable.Lastatau Enumerable.Single, Anda dapat mengganti metode alternatif, seperti Enumerable.FirstOrDefault, , Enumerable.LastOrDefaultatau Enumerable.SingleOrDefault, yang mengembalikan nilai default alih-alih anggota urutan.
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 angka, dan metode menghasilkan pengecualian InvalidOperationException.
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: {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 {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 Enumerable.FirstOrDefault alih-alih Enumerable.First untuk 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 .
Nota
Menginterpretasikan nilai yang dikembalikan oleh metode Enumerable.FirstOrDefault sering kali diperumit oleh fakta bahwa nilai default tipe 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 metode Enumerable.FirstOrDefault<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>) untuk mencegah pengecualian InvalidOperationException yang 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 {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 Enumerable.SingleOrDefault ini masih melemparkan pengecualian InvalidOperationException ketika urutannya mengandung lebih dari satu unsur.
Tabel berikut mencantumkan pesan pengecualian dari objek pengecualian InvalidOperationException yang dilemparkan oleh panggilan ke metode Enumerable.Single 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 metode Enumerable.Single menghasilkan pengecualian InvalidOperationException karena dalam urutannya tidak ada 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($"{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()
Contoh berikut mencoba mencegah pengecualian InvalidOperationException yang dilemparkan saat urutan kosong dengan cara memanggil metode Enumerable.SingleOrDefault. 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($"{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()
Memanggil metode Enumerable.Single mengasumsikan bahwa suatu 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 disengaja di pihak Anda dan kondisi ini tidak terpenuhi, melemparkan kembali atau menangkap hasilnya InvalidOperationException adalah hal yang tepat. 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.
Melemparkan pengecualian InvalidOperationException
Anda harus melemparkan InvalidOperationException pengecualian hanya ketika status objek Anda karena alasan tertentu tidak mendukung panggilan metode tertentu. Artinya, panggilan metode itu valid dalam beberapa keadaan atau konteks, tetapi tidak valid di keadaan atau konteks 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.