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:
- 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 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 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 danfalse
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 ketrue
. - Kontrol tombol bernama
threadExampleBtn
. Contoh ini menyediakan handler,ThreadsExampleBtn_Click
, untuk peristiwa tombolClick
.
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-alihforeach
, ,for...in
atauFor 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 mengurutkanPerson
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:
- Nullable<T>.HasValue Gunakan properti untuk memilih hanya elemen yang bukan
null
. - Panggil salah Nullable<T>.GetValueOrDefault satu kelebihan beban untuk memberikan nilai default untuk sebuah
null
nilai.
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.
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 menumbuhkan kembali pengecualian sudah tepat.
Jika kegagalan Anda memeriksa urutan kosong tidak disengaja, Anda dapat memanggil salah satu kelebihan beban Enumerable.Any kelebihan beban untuk menentukan apakah urutan berisi elemen apa pun.
Tip
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, 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.