Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
In dit artikel vindt u aanvullende opmerkingen in de referentiedocumentatie voor deze API.
InvalidOperationException wordt gebruikt in gevallen waarin het niet aanroepen van een methode wordt veroorzaakt door andere redenen dan ongeldige argumenten. Normaal gesproken wordt deze gegenereerd wanneer de status van een object de methodeaanroep niet kan ondersteunen. Een InvalidOperationException uitzondering wordt bijvoorbeeld gegenereerd door methoden zoals:
- IEnumerator.MoveNext als objecten van een verzameling worden gewijzigd nadat de enumerator is gemaakt. Zie Een verzameling wijzigen tijdens het herhalenvoor meer informatie.
- ResourceSet.GetString als de resourceset wordt gesloten voordat de methode-aanroep wordt uitgevoerd.
- XContainer.Add, als het object of de objecten die moeten worden toegevoegd, een onjuist gestructureerd XML-document oplevert.
- Een methode die probeert de gebruikersinterface te bewerken vanuit een thread die niet de hoofd- of UI-thread is.
Belangrijk
Omdat de InvalidOperationException uitzondering in een groot aantal omstandigheden kan worden gegenereerd, is het belangrijk om het uitzonderingsbericht te lezen dat wordt geretourneerd door de eigenschap Message.
InvalidOperationException gebruikt de HRESULT-COR_E_INVALIDOPERATION
, met de waarde 0x80131509.
Voor een lijst van initiële eigenschapswaarden voor een exemplaar van InvalidOperationException, zie de InvalidOperationException-constructoren.
Veelvoorkomende oorzaken van InvalidOperationException-uitzonderingen
In de volgende secties ziet u hoe in sommige veelvoorkomende gevallen de InvalidOperationException-uitzondering in een app optreedt. Hoe u het probleem afhandelt, is afhankelijk van de specifieke situatie. De uitzondering wordt meestal echter veroorzaakt door een fout in de ontwikkelaar en de InvalidOperationException uitzondering kan worden verwacht en vermeden.
Een UI-thread bijwerken vanuit een niet-UI-thread
Werkthreads worden vaak gebruikt om achtergrondwerk uit te voeren waarbij gegevens worden verzameld die in de gebruikersinterface van een toepassing moeten worden weergegeven. Echter. De meeste GUI-toepassingsframeworks (grafische gebruikersinterface) voor .NET, zoals Windows Forms en Windows Presentation Foundation (WPF), bieden u alleen toegang tot GUI-objecten vanuit de thread waarmee de gebruikersinterface (de hoofd- of ui-thread) wordt gemaakt en beheerd. Er wordt een InvalidOperationException gegenereerd wanneer u probeert toegang te krijgen tot een UI-element vanuit een andere thread dan de UI-thread. De tekst van het uitzonderingsbericht wordt weergegeven in de volgende tabel.
Toepassingstype | Bericht |
---|---|
WPF-app | De aanroepende thread heeft geen toegang tot dit object omdat een andere thread eigenaar is van dit object. |
UWP-app | De toepassing heeft een interface genoemd die voor een andere thread werd marshaled. |
Windows Forms-app | bewerking voor meerdere threads is ongeldig: Besturingselement 'Tekstvak1' dat is geopend vanuit een andere thread dan de thread waarop deze is gemaakt. |
UI-frameworks voor .NET implementeren een dispatcher patroon dat een methode bevat om te controleren of een aanroep naar een lid van een UI-element wordt uitgevoerd op de UI-thread en andere methoden om de aanroep op de UI-thread te plannen:
- Roep in WPF-apps de Dispatcher.CheckAccess methode aan om te bepalen of een methode wordt uitgevoerd op een niet-UI-thread. Het retourneert
true
als de methode wordt uitgevoerd op de UI-thread en andersfalse
. Roep een van de overbelastingen van de Dispatcher.Invoke methode aan om de aanroep op de UI-thread te plannen. - Controleer in UWP-apps de eigenschap CoreDispatcher.HasThreadAccess om te bepalen of een methode wordt uitgevoerd op een niet-UI-thread. Roep de CoreDispatcher.RunAsync methode aan om een gemachtigde uit te voeren waarmee de UI-thread wordt bijgewerkt.
- Gebruik in Windows Forms-apps de eigenschap Control.InvokeRequired om te bepalen of een methode wordt uitgevoerd op een niet-UI-thread. Roep een van de overloads van de Control.Invoke-methode aan om een gedelegeerde uit te voeren die de UI-thread bijwerkt.
In de volgende voorbeelden ziet u de InvalidOperationException uitzondering die wordt gegenereerd wanneer u probeert een UI-element bij te werken vanuit een andere thread dan de thread die deze heeft gemaakt. Voor elk voorbeeld moet u twee besturingselementen maken:
- Een tekstvakcontrole met de naam
textBox1
. In een Windows Forms-app moet u de bijbehorende eigenschap Multiline instellen optrue
. - Een knop besturingselement met de naam
threadExampleBtn
. Het voorbeeld bevat een handler,ThreadsExampleBtn_Click
, voor hetClick
event van de knop.
In elk geval roept de threadExampleBtn_Click
gebeurtenishandler de DoSomeWork
methode tweemaal aan. De eerste aanroep wordt synchroon uitgevoerd en slaagt. Maar de tweede aanroep, omdat deze asynchroon wordt uitgevoerd op een thread van een thread-pool, probeert de gebruikersinterface bij te werken vanuit een niet-gebruikersinterface-thread. Dit resulteert in een InvalidOperationException uitzondering.
WPF-apps
private async void threadExampleBtn_Click(object sender, RoutedEventArgs e)
{
textBox1.Text = String.Empty;
textBox1.Text = "Simulating work on UI thread.\n";
DoSomeWork(20);
textBox1.Text += "Work completed...\n";
textBox1.Text += "Simulating work on non-UI thread.\n";
await Task.Run(() => DoSomeWork(1000));
textBox1.Text += "Work completed...\n";
}
private async void DoSomeWork(int milliseconds)
{
// Simulate work.
await Task.Delay(milliseconds);
// Report completion.
var msg = String.Format("Some work completed in {0} ms.\n", milliseconds);
textBox1.Text += msg;
}
Met de volgende versie van de methode DoSomeWork
wordt de uitzondering in een WPF-app geëlimineerd.
private async void DoSomeWork(int milliseconds)
{
// Simulate work.
await Task.Delay(milliseconds);
// Report completion.
bool uiAccess = textBox1.Dispatcher.CheckAccess();
String msg = String.Format("Some work completed in {0} ms. on {1}UI thread\n",
milliseconds, uiAccess ? String.Empty : "non-");
if (uiAccess)
textBox1.Text += msg;
else
textBox1.Dispatcher.Invoke(() => { textBox1.Text += msg; });
}
Windows Forms-apps
List<String> lines = new List<String>();
private async void threadExampleBtn_Click(object sender, EventArgs e)
{
textBox1.Text = String.Empty;
lines.Clear();
lines.Add("Simulating work on UI thread.");
textBox1.Lines = lines.ToArray();
DoSomeWork(20);
lines.Add("Simulating work on non-UI thread.");
textBox1.Lines = lines.ToArray();
await Task.Run(() => DoSomeWork(1000));
lines.Add("ThreadsExampleBtn_Click completes. ");
textBox1.Lines = lines.ToArray();
}
private async void DoSomeWork(int milliseconds)
{
// simulate work
await Task.Delay(milliseconds);
// report completion
lines.Add(String.Format("Some work completed in {0} ms on UI thread.", milliseconds));
textBox1.Lines = lines.ToArray();
}
Dim lines As New List(Of String)()
Private Async Sub threadExampleBtn_Click(sender As Object, e As EventArgs) Handles Button1.Click
TextBox1.Text = String.Empty
lines.Clear()
lines.Add("Simulating work on UI thread.")
TextBox1.Lines = lines.ToArray()
DoSomeWork(20)
lines.Add("Simulating work on non-UI thread.")
TextBox1.Lines = lines.ToArray()
Await Task.Run(Sub() DoSomeWork(1000))
lines.Add("ThreadsExampleBtn_Click completes. ")
TextBox1.Lines = lines.ToArray()
End Sub
Private Async Sub DoSomeWork(milliseconds As Integer)
' Simulate work.
Await Task.Delay(milliseconds)
' Report completion.
lines.Add(String.Format("Some work completed in {0} ms on UI thread.", milliseconds))
textBox1.Lines = lines.ToArray()
End Sub
Met de volgende versie van de methode DoSomeWork
wordt de uitzondering in een Windows Forms-app geëlimineerd.
private async void DoSomeWork(int milliseconds)
{
// simulate work
await Task.Delay(milliseconds);
// Report completion.
bool uiMarshal = textBox1.InvokeRequired;
String msg = String.Format("Some work completed in {0} ms. on {1}UI thread\n",
milliseconds, uiMarshal ? String.Empty : "non-");
lines.Add(msg);
if (uiMarshal) {
textBox1.Invoke(new Action(() => { textBox1.Lines = lines.ToArray(); }));
}
else {
textBox1.Lines = lines.ToArray();
}
}
Private Async Sub DoSomeWork(milliseconds As Integer)
' Simulate work.
Await Task.Delay(milliseconds)
' Report completion.
Dim uiMarshal As Boolean = TextBox1.InvokeRequired
Dim msg As String = String.Format("Some work completed in {0} ms. on {1}UI thread" + vbCrLf,
milliseconds, If(uiMarshal, String.Empty, "non-"))
lines.Add(msg)
If uiMarshal Then
TextBox1.Invoke(New Action(Sub() TextBox1.Lines = lines.ToArray()))
Else
TextBox1.Lines = lines.ToArray()
End If
End Sub
Een verzameling wijzigen tijdens het itereren
De instructie foreach
in C#, for...in
in F# of For Each
instructie in Visual Basic wordt gebruikt om de leden van een verzameling te herhalen en de afzonderlijke elementen ervan te lezen of te wijzigen. Het kan echter niet worden gebruikt om items toe te voegen aan of te verwijderen uit de verzameling. Als u dit doet, wordt er een InvalidOperationException uitzondering gegenereerd met een bericht dat lijkt op'Verzameling is gewijzigd; opsommingsbewerking kan niet worden uitgevoerd."
In het volgende voorbeeld wordt een verzameling gehele getallen herhaald om het vierkant van elk geheel getal toe te voegen aan de verzameling. In het voorbeeld wordt een InvalidOperationException bij de eerste oproep van de methode List<T>.Add.
using System;
using System.Collections.Generic;
public class IteratingEx1
{
public static void Main()
{
var numbers = new List<int>() { 1, 2, 3, 4, 5 };
foreach (var number in numbers)
{
int square = (int)Math.Pow(number, 2);
Console.WriteLine($"{number}^{square}");
Console.WriteLine($"Adding {square} to the collection...");
Console.WriteLine();
numbers.Add(square);
}
}
}
// The example displays the following output:
// 1^1
// Adding 1 to the collection...
//
//
// Unhandled Exception: System.InvalidOperationException: Collection was modified;
// enumeration operation may not execute.
// at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
// at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
// at Example.Main()
open System
let numbers = ResizeArray [| 1; 2; 3; 4; 5 |]
for number in numbers do
let square = Math.Pow(number, 2) |> int
printfn $"{number}^{square}"
printfn $"Adding {square} to the collection...\n"
numbers.Add square
// The example displays the following output:
// 1^1
// Adding 1 to the collection...
//
//
// Unhandled Exception: System.InvalidOperationException: Collection was modified
// enumeration operation may not execute.
// at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
// at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
// at <StartupCode$fs>.main()
Imports System.Collections.Generic
Module Example6
Public Sub Main()
Dim numbers As New List(Of Integer)({1, 2, 3, 4, 5})
For Each number In numbers
Dim square As Integer = CInt(Math.Pow(number, 2))
Console.WriteLine("{0}^{1}", number, square)
Console.WriteLine("Adding {0} to the collection..." + vbCrLf,
square)
numbers.Add(square)
Next
End Sub
End Module
' The example displays the following output:
' 1^1
' Adding 1 to the collection...
'
'
' Unhandled Exception: System.InvalidOperationException: Collection was modified;
' enumeration operation may not execute.
' at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
' at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
' at Example.Main()
U kunt de uitzondering op twee manieren elimineren, afhankelijk van uw toepassingslogica:
Als elementen moeten worden toegevoegd aan de verzameling tijdens het itereren, kunt u deze itereren met behulp van een index met de instructie
for
(for..to
in F#) in plaats vanforeach
,for...in
ofFor Each
. In het volgende voorbeeld wordt de for-instructie gebruikt om het kwadrat van getallen in de verzameling toe te voegen aan de verzameling.using System; using System.Collections.Generic; public class IteratingEx2 { public static void Main() { var numbers = new List<int>() { 1, 2, 3, 4, 5 }; int upperBound = numbers.Count - 1; for (int ctr = 0; ctr <= upperBound; ctr++) { int square = (int)Math.Pow(numbers[ctr], 2); Console.WriteLine($"{numbers[ctr]}^{square}"); Console.WriteLine($"Adding {square} to the collection..."); Console.WriteLine(); numbers.Add(square); } Console.WriteLine("Elements now in the collection: "); foreach (var number in numbers) Console.Write("{0} ", number); } } // The example displays the following output: // 1^1 // Adding 1 to the collection... // // 2^4 // Adding 4 to the collection... // // 3^9 // Adding 9 to the collection... // // 4^16 // Adding 16 to the collection... // // 5^25 // Adding 25 to the collection... // // Elements now in the collection: // 1 2 3 4 5 1 4 9 16 25
open System open System.Collections.Generic let numbers = ResizeArray [| 1; 2; 3; 4; 5 |] let upperBound = numbers.Count - 1 for i = 0 to upperBound do let square = Math.Pow(numbers[i], 2) |> int printfn $"{numbers[i]}^{square}" printfn $"Adding {square} to the collection...\n" numbers.Add square printfn "Elements now in the collection: " for number in numbers do printf $"{number} " // The example displays the following output: // 1^1 // Adding 1 to the collection... // // 2^4 // Adding 4 to the collection... // // 3^9 // Adding 9 to the collection... // // 4^16 // Adding 16 to the collection... // // 5^25 // Adding 25 to the collection... // // Elements now in the collection: // 1 2 3 4 5 1 4 9 16 25
Imports System.Collections.Generic Module Example7 Public Sub Main() Dim numbers As New List(Of Integer)({1, 2, 3, 4, 5}) Dim upperBound = numbers.Count - 1 For ctr As Integer = 0 To upperBound Dim square As Integer = CInt(Math.Pow(numbers(ctr), 2)) Console.WriteLine("{0}^{1}", numbers(ctr), square) Console.WriteLine("Adding {0} to the collection..." + vbCrLf, square) numbers.Add(square) Next Console.WriteLine("Elements now in the collection: ") For Each number In numbers Console.Write("{0} ", number) Next End Sub End Module ' The example displays the following output: ' 1^1 ' Adding 1 to the collection... ' ' 2^4 ' Adding 4 to the collection... ' ' 3^9 ' Adding 9 to the collection... ' ' 4^16 ' Adding 16 to the collection... ' ' 5^25 ' Adding 25 to the collection... ' ' Elements now in the collection: ' 1 2 3 4 5 1 4 9 16 25
Houd er rekening mee dat u het aantal iteraties moet instellen voordat u de verzameling itereert door een teller in de lus te gebruiken die de lus op de juiste manier verlaat, door achteruit te herhalen, van
Count
- 1 tot 0, of, zoals in het voorbeeld, door het aantal elementen in de matrix toe te wijzen aan een variabele en deze te gebruiken om de bovengrens van de lus vast te stellen. Als er op elke iteratie een element aan de verzameling wordt toegevoegd, resulteert een eindeloze lus.Als het niet nodig is om elementen toe te voegen aan de verzameling tijdens het herhalen, kunt u de elementen opslaan die moeten worden toegevoegd aan een tijdelijke verzameling die u toevoegt wanneer de verzameling is voltooid. In het volgende voorbeeld wordt deze methode gebruikt om het kwadrat van getallen in een verzameling toe te voegen aan een tijdelijke verzameling en vervolgens de verzamelingen te combineren in één matrixobject.
using System; using System.Collections.Generic; public class IteratingEx3 { public static void Main() { var numbers = new List<int>() { 1, 2, 3, 4, 5 }; var temp = new List<int>(); // Square each number and store it in a temporary collection. foreach (var number in numbers) { int square = (int)Math.Pow(number, 2); temp.Add(square); } // Combine the numbers into a single array. int[] combined = new int[numbers.Count + temp.Count]; Array.Copy(numbers.ToArray(), 0, combined, 0, numbers.Count); Array.Copy(temp.ToArray(), 0, combined, numbers.Count, temp.Count); // Iterate the array. foreach (var value in combined) Console.Write("{0} ", value); } } // The example displays the following output: // 1 2 3 4 5 1 4 9 16 25
open System open System.Collections.Generic let numbers = ResizeArray [| 1; 2; 3; 4; 5 |] let temp = ResizeArray() // Square each number and store it in a temporary collection. for number in numbers do let square = Math.Pow(number, 2) |> int temp.Add square // Combine the numbers into a single array. let combined = Array.zeroCreate<int> (numbers.Count + temp.Count) Array.Copy(numbers.ToArray(), 0, combined, 0, numbers.Count) Array.Copy(temp.ToArray(), 0, combined, numbers.Count, temp.Count) // Iterate the array. for value in combined do printf $"{value} " // The example displays the following output: // 1 2 3 4 5 1 4 9 16 25
Imports System.Collections.Generic Module Example8 Public Sub Main() Dim numbers As New List(Of Integer)({1, 2, 3, 4, 5}) Dim temp As New List(Of Integer)() ' Square each number and store it in a temporary collection. For Each number In numbers Dim square As Integer = CInt(Math.Pow(number, 2)) temp.Add(square) Next ' Combine the numbers into a single array. Dim combined(numbers.Count + temp.Count - 1) As Integer Array.Copy(numbers.ToArray(), 0, combined, 0, numbers.Count) Array.Copy(temp.ToArray(), 0, combined, numbers.Count, temp.Count) ' Iterate the array. For Each value In combined Console.Write("{0} ", value) Next End Sub End Module ' The example displays the following output: ' 1 2 3 4 5 1 4 9 16 25
Een matrix of verzameling sorteren waarvan objecten niet kunnen worden vergeleken
Sorteermethoden voor algemeen gebruik, zoals de methode Array.Sort(Array) of de methode List<T>.Sort(), vereisen meestal dat ten minste één van de objecten moet worden gesorteerd om de IComparable<T> of de IComparable-interface te implementeren. Zo niet, kan de verzameling of matrix niet worden gesorteerd en de methode genereert een InvalidOperationException uitzondering. In het volgende voorbeeld wordt een Person
-klasse gedefinieerd, worden twee Person
objecten opgeslagen in een algemeen List<T>-object en wordt geprobeerd deze te sorteren. Zoals de uitvoer uit het voorbeeld laat zien, genereert de aanroep van de methode List<T>.Sort() een InvalidOperationException.
using System;
using System.Collections.Generic;
public class Person1
{
public Person1(string fName, string lName)
{
FirstName = fName;
LastName = lName;
}
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class ListSortEx1
{
public static void Main()
{
var people = new List<Person1>();
people.Add(new Person1("John", "Doe"));
people.Add(new Person1("Jane", "Doe"));
people.Sort();
foreach (var person in people)
Console.WriteLine($"{person.FirstName} {person.LastName}");
}
}
// The example displays the following output:
// Unhandled Exception: System.InvalidOperationException: Failed to compare two elements in the array. --->
// System.ArgumentException: At least one object must implement IComparable.
// at System.Collections.Comparer.Compare(Object a, Object b)
// at System.Collections.Generic.ArraySortHelper`1.SwapIfGreater(T[] keys, IComparer`1 comparer, Int32 a, Int32 b)
// at System.Collections.Generic.ArraySortHelper`1.DepthLimitedQuickSort(T[] keys, Int32 left, Int32 right, IComparer`1 comparer, Int32 depthLimit)
// at System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index, Int32 length, IComparer`1 comparer)
// --- End of inner exception stack trace ---
// at System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index, Int32 length, IComparer`1 comparer)
// at System.Array.Sort[T](T[] array, Int32 index, Int32 length, IComparer`1 comparer)
// at System.Collections.Generic.List`1.Sort(Int32 index, Int32 count, IComparer`1 comparer)
// at Example.Main()
type Person(firstName: string, lastName: string) =
member val FirstName = firstName with get, set
member val LastName = lastName with get, set
let people = ResizeArray()
people.Add(Person("John", "Doe"))
people.Add(Person("Jane", "Doe"))
people.Sort()
for person in people do
printfn $"{person.FirstName} {person.LastName}"
// The example displays the following output:
// Unhandled Exception: System.InvalidOperationException: Failed to compare two elements in the array. --->
// System.ArgumentException: At least one object must implement IComparable.
// at System.Collections.Comparer.Compare(Object a, Object b)
// at System.Collections.Generic.ArraySortHelper`1.SwapIfGreater(T[] keys, IComparer`1 comparer, Int32 a, Int32 b)
// at System.Collections.Generic.ArraySortHelper`1.DepthLimitedQuickSort(T[] keys, Int32 left, Int32 right, IComparer`1 comparer, Int32 depthLimit)
// at System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index, Int32 length, IComparer`1 comparer)
// --- End of inner exception stack trace ---
// at System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index, Int32 length, IComparer`1 comparer)
// at System.Array.Sort[T](T[] array, Int32 index, Int32 length, IComparer`1 comparer)
// at System.Collections.Generic.List`1.Sort(Int32 index, Int32 count, IComparer`1 comparer)
// at <StartupCode$fs>.main()
Imports System.Collections.Generic
Public Class Person9
Public Sub New(fName As String, lName As String)
FirstName = fName
LastName = lName
End Sub
Public Property FirstName As String
Public Property LastName As String
End Class
Module Example9
Public Sub Main()
Dim people As New List(Of Person9)()
people.Add(New Person9("John", "Doe"))
people.Add(New Person9("Jane", "Doe"))
people.Sort()
For Each person In people
Console.WriteLine("{0} {1}", person.FirstName, person.LastName)
Next
End Sub
End Module
' The example displays the following output:
' Unhandled Exception: System.InvalidOperationException: Failed to compare two elements in the array. --->
' System.ArgumentException: At least one object must implement IComparable.
' at System.Collections.Comparer.Compare(Object a, Object b)
' at System.Collections.Generic.ArraySortHelper`1.SwapIfGreater(T[] keys, IComparer`1 comparer, Int32 a, Int32 b)
' at System.Collections.Generic.ArraySortHelper`1.DepthLimitedQuickSort(T[] keys, Int32 left, Int32 right, IComparer`1 comparer, Int32 depthLimit)
' at System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index, Int32 length, IComparer`1 comparer)
' --- End of inner exception stack trace ---
' at System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index, Int32 length, IComparer`1 comparer)
' at System.Array.Sort[T](T[] array, Int32 index, Int32 length, IComparer`1 comparer)
' at System.Collections.Generic.List`1.Sort(Int32 index, Int32 count, IComparer`1 comparer)
' at Example.Main()
U kunt de uitzondering op drie manieren elimineren:
Als u de eigenaar kunt zijn van het type dat u probeert te sorteren (dat wil zeggen, als u de broncode bepaalt), kunt u dit wijzigen om de IComparable<T> of de IComparable-interface te implementeren. Hiervoor moet u de IComparable<T>.CompareTo of de methode CompareTo implementeren. Het toevoegen van een interface-implementatie aan een bestaand type is geen belangrijke wijziging.
In het volgende voorbeeld wordt deze methode gebruikt om een IComparable<T>-implementatie te bieden voor de
Person
-klasse. U kunt de algemene sorteermethode van de verzameling of matrix nog steeds aanroepen en, zoals de uitvoer uit het voorbeeld laat zien, wordt de verzameling succesvol gesorteerd.using System; using System.Collections.Generic; public class Person2 : IComparable<Person> { public Person2(String fName, String lName) { FirstName = fName; LastName = lName; } public String FirstName { get; set; } public String LastName { get; set; } public int CompareTo(Person other) { return String.Format("{0} {1}", LastName, FirstName). CompareTo(String.Format("{0} {1}", other.LastName, other.FirstName)); } } public class ListSortEx2 { public static void Main() { var people = new List<Person2>(); people.Add(new Person2("John", "Doe")); people.Add(new Person2("Jane", "Doe")); people.Sort(); foreach (var person in people) Console.WriteLine($"{person.FirstName} {person.LastName}"); } } // The example displays the following output: // Jane Doe // John Doe
open System type Person(firstName: string, lastName: string) = member val FirstName = firstName with get, set member val LastName = lastName with get, set interface IComparable<Person> with member this.CompareTo(other) = compare $"{this.LastName} {this.FirstName}" $"{other.LastName} {other.FirstName}" let people = ResizeArray() people.Add(new Person("John", "Doe")) people.Add(new Person("Jane", "Doe")) people.Sort() for person in people do printfn $"{person.FirstName} {person.LastName}" // The example displays the following output: // Jane Doe // John Doe
Imports System.Collections.Generic Public Class Person : Implements IComparable(Of Person) Public Sub New(fName As String, lName As String) FirstName = fName LastName = lName End Sub Public Property FirstName As String Public Property LastName As String Public Function CompareTo(other As Person) As Integer _ Implements IComparable(Of Person).CompareTo Return String.Format("{0} {1}", LastName, FirstName). CompareTo(String.Format("{0} {1}", other.LastName, other.FirstName)) End Function End Class Module Example10 Public Sub Main() Dim people As New List(Of Person)() people.Add(New Person("John", "Doe")) people.Add(New Person("Jane", "Doe")) people.Sort() For Each person In people Console.WriteLine("{0} {1}", person.FirstName, person.LastName) Next End Sub End Module ' The example displays the following output: ' Jane Doe ' John Doe
Als u de broncode niet kunt wijzigen voor het type dat u wilt sorteren, kunt u een sorteerklasse voor speciaal doel definiëren waarmee de IComparer<T>-interface wordt geïmplementeerd. U kunt een overbelasting aanroepen van de
Sort
methode die een IComparer<T> parameter bevat. Deze methode is vooral handig als u een speciale sorteerklasse wilt ontwikkelen waarmee objecten kunnen worden gesorteerd op basis van meerdere criteria.In het volgende voorbeeld wordt de benadering gebruikt door een aangepaste
PersonComparer
-klasse te ontwikkelen die wordt gebruikt omPerson
verzamelingen te sorteren. Vervolgens wordt een exemplaar van deze klasse doorgegeven aan de methode List<T>.Sort(IComparer<T>).using System; using System.Collections.Generic; public class Person3 { public Person3(String fName, String lName) { FirstName = fName; LastName = lName; } public String FirstName { get; set; } public String LastName { get; set; } } public class PersonComparer : IComparer<Person3> { public int Compare(Person3 x, Person3 y) { return String.Format("{0} {1}", x.LastName, x.FirstName). CompareTo(String.Format("{0} {1}", y.LastName, y.FirstName)); } } public class ListSortEx3 { public static void Main() { var people = new List<Person3>(); people.Add(new Person3("John", "Doe")); people.Add(new Person3("Jane", "Doe")); people.Sort(new PersonComparer()); foreach (var person in people) Console.WriteLine($"{person.FirstName} {person.LastName}"); } } // The example displays the following output: // Jane Doe // John Doe
open System open System.Collections.Generic type Person(firstName, lastName) = member val FirstName = firstName with get, set member val LastName = lastName with get, set type PersonComparer() = interface IComparer<Person> with member _.Compare(x: Person, y: Person) = $"{x.LastName} {x.FirstName}".CompareTo $"{y.LastName} {y.FirstName}" let people = ResizeArray() people.Add(Person("John", "Doe")) people.Add(Person("Jane", "Doe")) people.Sort(PersonComparer()) for person in people do printfn $"{person.FirstName} {person.LastName}" // The example displays the following output: // Jane Doe // John Doe
Imports System.Collections.Generic Public Class Person11 Public Sub New(fName As String, lName As String) FirstName = fName LastName = lName End Sub Public Property FirstName As String Public Property LastName As String End Class Public Class PersonComparer : Implements IComparer(Of Person11) Public Function Compare(x As Person11, y As Person11) As Integer _ Implements IComparer(Of Person11).Compare Return String.Format("{0} {1}", x.LastName, x.FirstName). CompareTo(String.Format("{0} {1}", y.LastName, y.FirstName)) End Function End Class Module Example11 Public Sub Main() Dim people As New List(Of Person11)() people.Add(New Person11("John", "Doe")) people.Add(New Person11("Jane", "Doe")) people.Sort(New PersonComparer()) For Each person In people Console.WriteLine("{0} {1}", person.FirstName, person.LastName) Next End Sub End Module ' The example displays the following output: ' Jane Doe ' John Doe
Als u de broncode niet kunt wijzigen voor het type dat u wilt sorteren, kunt u een Comparison<T> gemachtigde maken om de sortering uit te voeren. De handtekening van de gemachtigde is
Function Comparison(Of T)(x As T, y As T) As Integer
int Comparison<T>(T x, T y)
In het volgende voorbeeld wordt de methode gebruikt door een
PersonComparison
methode te definiëren die overeenkomt met de Comparison<T> handtekening voor gemachtigden. Vervolgens wordt deze gemachtigde doorgegeven aan de methode List<T>.Sort(Comparison<T>).using System; using System.Collections.Generic; public class Person { public Person(String fName, String lName) { FirstName = fName; LastName = lName; } public String FirstName { get; set; } public String LastName { get; set; } } public class ListSortEx4 { public static void Main() { var people = new List<Person>(); people.Add(new Person("John", "Doe")); people.Add(new Person("Jane", "Doe")); people.Sort(PersonComparison); foreach (var person in people) Console.WriteLine($"{person.FirstName} {person.LastName}"); } public static int PersonComparison(Person x, Person y) { return String.Format("{0} {1}", x.LastName, x.FirstName). CompareTo(String.Format("{0} {1}", y.LastName, y.FirstName)); } } // The example displays the following output: // Jane Doe // John Doe
open System open System.Collections.Generic type Person(firstName, lastName) = member val FirstName = firstName with get, set member val LastName = lastName with get, set let personComparison (x: Person) (y: Person) = $"{x.LastName} {x.FirstName}".CompareTo $"{y.LastName} {y.FirstName}" let people = ResizeArray() people.Add(Person("John", "Doe")) people.Add(Person("Jane", "Doe")) people.Sort personComparison for person in people do printfn $"{person.FirstName} {person.LastName}" // The example displays the following output: // Jane Doe // John Doe
Imports System.Collections.Generic Public Class Person12 Public Sub New(fName As String, lName As String) FirstName = fName LastName = lName End Sub Public Property FirstName As String Public Property LastName As String End Class Module Example12 Public Sub Main() Dim people As New List(Of Person12)() people.Add(New Person12("John", "Doe")) people.Add(New Person12("Jane", "Doe")) people.Sort(AddressOf PersonComparison) For Each person In people Console.WriteLine("{0} {1}", person.FirstName, person.LastName) Next End Sub Public Function PersonComparison(x As Person12, y As Person12) As Integer Return String.Format("{0} {1}", x.LastName, x.FirstName). CompareTo(String.Format("{0} {1}", y.LastName, y.FirstName)) End Function End Module ' The example displays the following output: ' Jane Doe ' John Doe
Het casten van een Nullable<T> dat null is naar zijn onderliggende type
Als u een Nullable<T>-waarde probeert te casten die null
is naar het onderliggende type, genereert dat een InvalidOperationException-uitzondering en wordt het foutbericht weergegeven: 'Nullable object moet een waarde hebben.
In het volgende voorbeeld wordt een InvalidOperationException uitzondering gegenereerd wanneer wordt geprobeerd een matrix te herhalen die een Nullable(Of Integer)
waarde bevat.
using System;
using System.Linq;
public class NullableEx1
{
public static void Main()
{
var queryResult = new int?[] { 1, 2, null, 4 };
var map = queryResult.Select(nullableInt => (int)nullableInt);
// Display list.
foreach (var num in map)
Console.Write("{0} ", num);
Console.WriteLine();
}
}
// The example displays the following output:
// 1 2
// Unhandled Exception: System.InvalidOperationException: Nullable object must have a value.
// at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
// at Example.<Main>b__0(Nullable`1 nullableInt)
// at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
// at Example.Main()
open System
open System.Linq
let queryResult = [| Nullable 1; Nullable 2; Nullable(); Nullable 4 |]
let map = queryResult.Select(fun nullableInt -> nullableInt.Value)
// Display list.
for num in map do
printf $"{num} "
printfn ""
// The example displays the following output:
// 1 2
// Unhandled Exception: System.InvalidOperationException: Nullable object must have a value.
// at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
// at Example.<Main>b__0(Nullable`1 nullableInt)
// at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
// at <StartupCode$fs>.main()
Imports System.Linq
Module Example13
Public Sub Main()
Dim queryResult = New Integer?() {1, 2, Nothing, 4}
Dim map = queryResult.Select(Function(nullableInt) CInt(nullableInt))
' Display list.
For Each num In map
Console.Write("{0} ", num)
Next
Console.WriteLine()
End Sub
End Module
' The example displays thIe following output:
' 1 2
' Unhandled Exception: System.InvalidOperationException: Nullable object must have a value.
' at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
' at Example.<Main>b__0(Nullable`1 nullableInt)
' at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
' at Example.Main()
Ga als volgende te werk om de uitzondering te voorkomen:
- Gebruik de eigenschap Nullable<T>.HasValue om alleen de elementen te selecteren die niet
null
zijn. - Roep een van de Nullable<T>.GetValueOrDefault overload-functies aan om een standaardwaarde op te geven voor een
null
waarde.
In het volgende voorbeeld worden beide gebruikt om de InvalidOperationException uitzondering te voorkomen.
using System;
using System.Linq;
public class NullableEx2
{
public static void Main()
{
var queryResult = new int?[] { 1, 2, null, 4 };
var numbers = queryResult.Select(nullableInt => (int)nullableInt.GetValueOrDefault());
// Display list using Nullable<int>.HasValue.
foreach (var number in numbers)
Console.Write("{0} ", number);
Console.WriteLine();
numbers = queryResult.Select(nullableInt => (int) (nullableInt.HasValue ? nullableInt : -1));
// Display list using Nullable<int>.GetValueOrDefault.
foreach (var number in numbers)
Console.Write("{0} ", number);
Console.WriteLine();
}
}
// The example displays the following output:
// 1 2 0 4
// 1 2 -1 4
open System
open System.Linq
let queryResult = [| Nullable 1; Nullable 2; Nullable(); Nullable 4 |]
let numbers = queryResult.Select(fun nullableInt -> nullableInt.GetValueOrDefault())
// Display list using Nullable<int>.HasValue.
for number in numbers do
printf $"{number} "
printfn ""
let numbers2 = queryResult.Select(fun nullableInt -> if nullableInt.HasValue then nullableInt.Value else -1)
// Display list using Nullable<int>.GetValueOrDefault.
for number in numbers2 do
printf $"{number} "
printfn ""
// The example displays the following output:
// 1 2 0 4
// 1 2 -1 4
Imports System.Linq
Module Example14
Public Sub Main()
Dim queryResult = New Integer?() {1, 2, Nothing, 4}
Dim numbers = queryResult.Select(Function(nullableInt) _
CInt(nullableInt.GetValueOrDefault()))
' Display list.
For Each number In numbers
Console.Write("{0} ", number)
Next
Console.WriteLine()
' Use -1 to indicate a missing values.
numbers = queryResult.Select(Function(nullableInt) _
CInt(If(nullableInt.HasValue, nullableInt, -1)))
' Display list.
For Each number In numbers
Console.Write("{0} ", number)
Next
Console.WriteLine()
End Sub
End Module
' The example displays the following output:
' 1 2 0 4
' 1 2 -1 4
Een System.Linq.Enumerable-methode aanroepen voor een lege verzameling
De Enumerable.Aggregate, Enumerable.Average, Enumerable.First, Enumerable.Last, Enumerable.Max, Enumerable.Min, Enumerable.Singleen Enumerable.SingleOrDefault methoden voeren bewerkingen uit op een reeks en retourneren één resultaat. Sommige overbelastingen van deze methoden veroorzaken een InvalidOperationException uitzondering wanneer de reeks leeg is, terwijl andere overbelastingen null
retourneren. De methode Enumerable.SingleOrDefault genereert ook een InvalidOperationException uitzondering wanneer de reeks meer dan één element bevat.
Notitie
De meeste methoden die een InvalidOperationException uitzondering veroorzaken, zijn overbelast. Zorg ervoor dat u het gedrag begrijpt van de overbelasting die u kiest.
De volgende tabel bevat de uitzonderingsberichten van de InvalidOperationException uitzonderingsobjecten die worden gegenereerd door aanroepen naar een aantal System.Linq.Enumerable methoden.
Methode | Bericht |
---|---|
Aggregate Average Last Max Min |
reeks bevat geen elementen |
First |
reeks bevat geen overeenkomend element |
Single SingleOrDefault |
reeks bevat meer dan één overeenkomend element |
Hoe u de uitzondering elimineert of afhandelt, is afhankelijk van de veronderstellingen van uw toepassing en van de specifieke methode die u aanroept.
Wanneer u bewust een van deze methoden aanroept zonder te controleren op een lege reeks, gaat u ervan uit dat de reeks niet leeg is en dat een lege reeks een onverwachte gebeurtenis is. In dit geval is het passend om de uitzondering te vangen of opnieuw te hergooien.
Als de controle op een lege reeks per ongeluk is mislukt, kunt u een van de overbelastingen van de Enumerable.Any aanroepen om te bepalen of een reeks elementen bevat.
Hint
Het aanroepen van de Enumerable.Any<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>) methode voordat een reeks wordt gegenereerd, kan de prestaties verbeteren als de gegevens die moeten worden verwerkt, een groot aantal elementen kunnen bevatten of als de bewerking waarmee de reeks wordt gegenereerd duur is.
Als u een methode zoals Enumerable.First, Enumerable.Lastof Enumerable.Singlehebt aangeroepen, kunt u een alternatieve methode vervangen, zoals Enumerable.FirstOrDefault, Enumerable.LastOrDefaultof Enumerable.SingleOrDefault, die een standaardwaarde retourneert in plaats van een lid van de reeks.
De voorbeelden bevatten aanvullende details.
In het volgende voorbeeld wordt de methode Enumerable.Average gebruikt om het gemiddelde van een reeks te berekenen waarvan de waarden groter zijn dan 4. Omdat er geen waarden uit de oorspronkelijke matrix groter zijn dan 4, worden er geen waarden opgenomen in de reeks en genereert de methode een InvalidOperationException uitzondering.
using System;
using System.Linq;
public class Example
{
public static void Main()
{
int[] data = { 1, 2, 3, 4 };
var average = data.Where(num => num > 4).Average();
Console.Write("The average of numbers greater than 4 is {0}",
average);
}
}
// The example displays the following output:
// Unhandled Exception: System.InvalidOperationException: Sequence contains no elements
// at System.Linq.Enumerable.Average(IEnumerable`1 source)
// at Example.Main()
open System
open System.Linq
let data = [| 1; 2; 3; 4 |]
let average =
data.Where(fun num -> num > 4).Average();
printfn $"The average of numbers greater than 4 is {average}"
// The example displays the following output:
// Unhandled Exception: System.InvalidOperationException: Sequence contains no elements
// at System.Linq.Enumerable.Average(IEnumerable`1 source)
// at <StartupCode$fs>.main()
Imports System.Linq
Module Example
Public Sub Main()
Dim data() As Integer = { 1, 2, 3, 4 }
Dim average = data.Where(Function(num) num > 4).Average()
Console.Write("The average of numbers greater than 4 is {0}",
average)
End Sub
End Module
' The example displays the following output:
' Unhandled Exception: System.InvalidOperationException: Sequence contains no elements
' at System.Linq.Enumerable.Average(IEnumerable`1 source)
' at Example.Main()
De uitzondering kan worden geëlimineerd door de methode Any aan te roepen om te bepalen of de reeks elementen bevat voordat de methode wordt aangeroepen die de reeks verwerkt, zoals in het volgende voorbeeld wordt weergegeven.
using System;
using System.Linq;
public class EnumerableEx2
{
public static void Main()
{
int[] dbQueryResults = { 1, 2, 3, 4 };
var moreThan4 = dbQueryResults.Where(num => num > 4);
if (moreThan4.Any())
Console.WriteLine($"Average value of numbers greater than 4: {moreThan4.Average()}:");
else
// handle empty collection
Console.WriteLine("The dataset has no values greater than 4.");
}
}
// The example displays the following output:
// The dataset has no values greater than 4.
open System
open System.Linq
let dbQueryResults = [| 1; 2; 3; 4 |]
let moreThan4 =
dbQueryResults.Where(fun num -> num > 4)
if moreThan4.Any() then
printfn $"Average value of numbers greater than 4: {moreThan4.Average()}:"
else
// handle empty collection
printfn "The dataset has no values greater than 4."
// The example displays the following output:
// The dataset has no values greater than 4.
Imports System.Linq
Module Example1
Public Sub Main()
Dim dbQueryResults() As Integer = {1, 2, 3, 4}
Dim moreThan4 = dbQueryResults.Where(Function(num) num > 4)
If moreThan4.Any() Then
Console.WriteLine("Average value of numbers greater than 4: {0}:",
moreThan4.Average())
Else
' Handle empty collection.
Console.WriteLine("The dataset has no values greater than 4.")
End If
End Sub
End Module
' The example displays the following output:
' The dataset has no values greater than 4.
De methode Enumerable.First retourneert het eerste item in een reeks of het eerste element in een reeks die voldoet aan een opgegeven voorwaarde. Als de reeks leeg is en dus geen eerste element heeft, wordt er een InvalidOperationException uitzondering gegenereerd.
In het volgende voorbeeld genereert de methode Enumerable.First<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>) een InvalidOperationException uitzondering omdat de matrix dbQueryResults geen element bevat dat groter is dan 4.
using System;
using System.Linq;
public class EnumerableEx3
{
public static void Main()
{
int[] dbQueryResults = { 1, 2, 3, 4 };
var firstNum = dbQueryResults.First(n => n > 4);
Console.WriteLine($"The first value greater than 4 is {firstNum}");
}
}
// The example displays the following output:
// Unhandled Exception: System.InvalidOperationException:
// Sequence contains no matching element
// at System.Linq.Enumerable.First[TSource](IEnumerable`1 source, Func`2 predicate)
// at Example.Main()
open System
open System.Linq
let dbQueryResults = [| 1; 2; 3; 4 |]
let firstNum = dbQueryResults.First(fun n -> n > 4)
printfn $"The first value greater than 4 is {firstNum}"
// The example displays the following output:
// Unhandled Exception: System.InvalidOperationException:
// Sequence contains no matching element
// at System.Linq.Enumerable.First[TSource](IEnumerable`1 source, Func`2 predicate)
// at <StartupCode$fs>.main()
Imports System.Linq
Module Example2
Public Sub Main()
Dim dbQueryResults() As Integer = {1, 2, 3, 4}
Dim firstNum = dbQueryResults.First(Function(n) n > 4)
Console.WriteLine("The first value greater than 4 is {0}",
firstNum)
End Sub
End Module
' The example displays the following output:
' Unhandled Exception: System.InvalidOperationException:
' Sequence contains no matching element
' at System.Linq.Enumerable.First[TSource](IEnumerable`1 source, Func`2 predicate)
' at Example.Main()
U kunt de methode Enumerable.FirstOrDefault aanroepen in plaats van Enumerable.First om een opgegeven of standaardwaarde te retourneren. Als de methode geen eerste element in de reeks vindt, wordt de standaardwaarde voor dat gegevenstype geretourneerd. De standaardwaarde is null
voor een verwijzingstype, nul voor een numeriek gegevenstype en DateTime.MinValue voor het DateTime type.
Notitie
Het interpreteren van de waarde die door de Enumerable.FirstOrDefault methode wordt geretourneerd, wordt vaak gecompliceerd door het feit dat de standaardwaarde van het type een geldige waarde in de reeks kan zijn. In dit geval roept u de Enumerable.Any methode aan om te bepalen of de reeks geldige leden heeft voordat u de methode Enumerable.First aanroept.
In het volgende voorbeeld wordt de methode Enumerable.FirstOrDefault<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>) aangeroepen om te voorkomen dat de InvalidOperationException exceptie uit het vorige voorbeeld optreedt.
using System;
using System.Linq;
public class EnumerableEx4
{
public static void Main()
{
int[] dbQueryResults = { 1, 2, 3, 4 };
var firstNum = dbQueryResults.FirstOrDefault(n => n > 4);
if (firstNum == 0)
Console.WriteLine("No value is greater than 4.");
else
Console.WriteLine($"The first value greater than 4 is {firstNum}");
}
}
// The example displays the following output:
// No value is greater than 4.
open System
open System.Linq
let dbQueryResults = [| 1; 2; 3; 4 |]
let firstNum = dbQueryResults.FirstOrDefault(fun n -> n > 4)
if firstNum = 0 then
printfn "No value is greater than 4."
else
printfn $"The first value greater than 4 is {firstNum}"
// The example displays the following output:
// No value is greater than 4.
Imports System.Linq
Module Example3
Public Sub Main()
Dim dbQueryResults() As Integer = {1, 2, 3, 4}
Dim firstNum = dbQueryResults.FirstOrDefault(Function(n) n > 4)
If firstNum = 0 Then
Console.WriteLine("No value is greater than 4.")
Else
Console.WriteLine("The first value greater than 4 is {0}",
firstNum)
End If
End Sub
End Module
' The example displays the following output:
' No value is greater than 4.
Enumerable.Single of Enumerable.SingleOrDefault aanroepen op een reeks zonder één element
De methode Enumerable.Single retourneert het enige element van een reeks of het enige element van een reeks dat voldoet aan een opgegeven voorwaarde. Als er geen elementen in de reeks staan of als er meer dan één element is, genereert de methode een InvalidOperationException uitzondering.
U kunt de methode Enumerable.SingleOrDefault gebruiken om een standaardwaarde te retourneren in plaats van een uitzondering te genereren wanneer de reeks geen elementen bevat. De methode Enumerable.SingleOrDefault genereert echter nog steeds een InvalidOperationException uitzondering wanneer de reeks meer dan één element bevat.
De volgende tabel bevat de uitzonderingsberichten van de InvalidOperationException uitzonderingsobjecten die worden gegenereerd door aanroepen naar de Enumerable.Single en Enumerable.SingleOrDefault methoden.
Methode | Bericht |
---|---|
Single |
reeks bevat geen overeenkomend element |
Single SingleOrDefault |
reeks bevat meer dan één overeenkomend element |
In het volgende voorbeeld genereert de aanroep van de methode Enumerable.Single een InvalidOperationException uitzondering omdat de reeks geen element groter dan 4 heeft.
using System;
using System.Linq;
public class EnumerableEx5
{
public static void Main()
{
int[] dbQueryResults = { 1, 2, 3, 4 };
var singleObject = dbQueryResults.Single(value => value > 4);
// Display results.
Console.WriteLine($"{singleObject} is the only value greater than 4");
}
}
// The example displays the following output:
// Unhandled Exception: System.InvalidOperationException:
// Sequence contains no matching element
// at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source, Func`2 predicate)
// at Example.Main()
open System
open System.Linq
let dbQueryResults = [| 1; 2; 3; 4 |]
let singleObject = dbQueryResults.Single(fun value -> value > 4)
// Display results.
printfn $"{singleObject} is the only value greater than 4"
// The example displays the following output:
// Unhandled Exception: System.InvalidOperationException:
// Sequence contains no matching element
// at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source, Func`2 predicate)
// at <StartupCode$fs>.main()
Imports System.Linq
Module Example4
Public Sub Main()
Dim dbQueryResults() As Integer = {1, 2, 3, 4}
Dim singleObject = dbQueryResults.Single(Function(value) value > 4)
' Display results.
Console.WriteLine("{0} is the only value greater than 4",
singleObject)
End Sub
End Module
' The example displays the following output:
' Unhandled Exception: System.InvalidOperationException:
' Sequence contains no matching element
' at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source, Func`2 predicate)
' at Example.Main()
In het volgende voorbeeld wordt geprobeerd te voorkomen dat de InvalidOperationException uitzondering optreedt wanneer een reeks leeg is door in plaats daarvan de Enumerable.SingleOrDefault methode aan te roepen. Omdat deze reeks echter meerdere elementen retourneert waarvan de waarde groter is dan 2, genereert deze ook een InvalidOperationException uitzondering.
using System;
using System.Linq;
public class EnumerableEx6
{
public static void Main()
{
int[] dbQueryResults = { 1, 2, 3, 4 };
var singleObject = dbQueryResults.SingleOrDefault(value => value > 2);
if (singleObject != 0)
Console.WriteLine($"{singleObject} is the only value greater than 2");
else
// Handle an empty collection.
Console.WriteLine("No value is greater than 2");
}
}
// The example displays the following output:
// Unhandled Exception: System.InvalidOperationException:
// Sequence contains more than one matching element
// at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source, Func`2 predicate)
// at Example.Main()
open System
open System.Linq
let dbQueryResults = [| 1; 2; 3; 4 |]
let singleObject = dbQueryResults.SingleOrDefault(fun value -> value > 2)
if singleObject <> 0 then
printfn $"{singleObject} is the only value greater than 2"
else
// Handle an empty collection.
printfn "No value is greater than 2"
// The example displays the following output:
// Unhandled Exception: System.InvalidOperationException:
// Sequence contains more than one matching element
// at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source, Func`2 predicate)
// at <StartupCode$fs>.main()
Imports System.Linq
Module Example5
Public Sub Main()
Dim dbQueryResults() As Integer = {1, 2, 3, 4}
Dim singleObject = dbQueryResults.SingleOrDefault(Function(value) value > 2)
If singleObject <> 0 Then
Console.WriteLine("{0} is the only value greater than 2",
singleObject)
Else
' Handle an empty collection.
Console.WriteLine("No value is greater than 2")
End If
End Sub
End Module
' The example displays the following output:
' Unhandled Exception: System.InvalidOperationException:
' Sequence contains more than one matching element
' at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source, Func`2 predicate)
' at Example.Main()
Bij het aanroepen van de methode Enumerable.Single wordt ervan uitgegaan dat een reeks of de reeks die voldoet aan opgegeven criteria slechts één element bevat. Enumerable.SingleOrDefault gaat uit van een reeks met nul of één resultaat, maar niet meer. Als deze aanname een opzettelijke aanname van uw kant is en niet aan deze voorwaarden wordt voldaan, is het gepast om de resulterende fout InvalidOperationException opnieuw te werpen of op te vangen. Anders, of als u verwacht dat er ongeldige voorwaarden met een bepaalde frequentie zullen optreden, kunt u overwegen een andere Enumerable-methode te gebruiken, zoals FirstOrDefault of Where.
Dynamische toegang tot domeindomeinen tussen toepassingen
De instructie OpCodes.Ldflda algemene tussentaal (CIL) genereert een InvalidOperationException uitzondering als het object met het veld waarvan u het adres wilt ophalen zich niet binnen het toepassingsdomein bevindt waarin uw code wordt uitgevoerd. Het adres van een veld kan alleen worden geopend vanuit het toepassingsdomein waarin het zich bevindt.
Een InvalidOperationException-uitzondering genereren
U moet alleen een InvalidOperationException uitzondering genereren wanneer de status van uw object om een of andere reden geen ondersteuning biedt voor een bepaalde methodeaanroep. Dat wil gezegd: de methode-aanroep is in sommige omstandigheden of contexten geldig, maar is ongeldig in andere.
Als de aanroepfout wordt veroorzaakt door ongeldige argumenten, moet in plaats daarvan ArgumentException of een van de afgeleide klassen, ArgumentNullException of ArgumentOutOfRangeException, worden gegooid.