System.InvalidOperationException – třída
Tento článek obsahuje doplňující poznámky k referenční dokumentaci pro toto rozhraní API.
InvalidOperationException se používá v případech, kdy selhání vyvolání metody je způsobeno jinými důvody než neplatnými argumenty. Obvykle se vyvolá, když stav objektu nemůže podporovat volání metody. Například výjimka InvalidOperationException je vyvolán metodami, jako jsou:
- IEnumerator.MoveNext pokud jsou objekty kolekce změněny po vytvoření enumerátoru. Další informace najdete v tématu Změna kolekce při iteraci.
- ResourceSet.GetString pokud je sada prostředků uzavřena před voláním metody.
- XContainer.Add, pokud by objekt nebo objekty, které mají být přidány, by vést k nesprávně strukturovanému dokumentu XML.
- Metoda, která se pokusí manipulovat s uživatelským rozhraním z vlákna, které není hlavním vláknem nebo vláknem uživatelského rozhraní.
Důležité
Vzhledem k tomu, že InvalidOperationException výjimku lze vyvolat v široké škále okolností, je důležité přečíst zprávu výjimky vrácenou Message vlastností.
InvalidOperationException používá HODNOTU HRESULT COR_E_INVALIDOPERATION
, která má hodnotu 0x80131509.
Seznam počátečních hodnot vlastností pro instanci InvalidOperationExceptionnaleznete v InvalidOperationException konstruktorech.
Běžné příčiny výjimek InvalidOperationException
Následující části ukazují, jak některé běžné případy, kdy je v aplikaci vyvolán výjimka InvalidOperationException . Způsob řešení problému závisí na konkrétní situaci. Nejčastěji však dochází k výjimce z chyby vývojáře a InvalidOperationException výjimku lze očekávat a vyhnout se.
Aktualizace vlákna uživatelského rozhraní z vlákna bez uživatelského rozhraní
Pracovní vlákna se často používají k provádění některých úloh na pozadí, které zahrnují shromažďování dat, která se mají zobrazit v uživatelském rozhraní aplikace. Nicméně. Většina aplikačních architektur grafického uživatelského rozhraní (grafické uživatelské rozhraní) pro .NET, jako jsou model Windows Forms a Windows Presentation Foundation (WPF), umožňuje přístup k objektům grafického uživatelského rozhraní pouze z vlákna, které vytváří a spravuje uživatelské rozhraní (hlavní vlákno nebo vlákno uživatelského rozhraní). Vyvolá InvalidOperationException se při pokusu o přístup k prvku uživatelského rozhraní z jiného vlákna než vlákna uživatelského rozhraní. Text zprávy o výjimce je uveden v následující tabulce.
Typ aplikace | Zpráva |
---|---|
Aplikace WPF | Volající vlákno nemůže získat přístup k tomuto objektu, protože ho vlastní jiné vlákno. |
Aplikace pro UPW | Aplikace volala rozhraní, které bylo zařazováno pro jiné vlákno. |
model Windows Forms aplikace | Operace křížového vlákna není platná: Ovládací prvek TextBox1 přístupný z jiného vlákna, než je vlákno, ve které bylo vytvořeno. |
Rozhraní uživatelského rozhraní pro .NET implementují model dispečera , který zahrnuje metodu, která kontroluje, jestli se volání člena prvku uživatelského rozhraní spouští ve vlákně uživatelského rozhraní a další metody pro naplánování volání ve vlákně uživatelského rozhraní:
- V aplikacích WPF zavolejte metodu Dispatcher.CheckAccess , která určí, jestli je metoda spuštěná ve vlákně bez uživatelského rozhraní.
true
Vrátí, pokud metoda běží ve vlákně uživatelského rozhraní afalse
v opačném případě. Volání jednoho z přetížení Dispatcher.Invoke metody naplánovat volání ve vlákně uživatelského rozhraní. - Vaplikacích CoreDispatcher.HasThreadAccess CoreDispatcher.RunAsync Voláním metody spusťte delegáta, který aktualizuje vlákno uživatelského rozhraní.
- V model Windows Forms aplikací pomocí Control.InvokeRequired vlastnosti určete, jestli je metoda spuštěná ve vlákně bez uživatelského rozhraní. Volání jednoho z přetížení Control.Invoke metody spuštění delegáta, který aktualizuje vlákno uživatelského rozhraní.
Následující příklady ilustrují InvalidOperationException výjimku, která se vyvolá při pokusu o aktualizaci prvku uživatelského rozhraní z jiného vlákna, než je vlákno, které ho vytvořilo. Každý příklad vyžaduje, abyste vytvořili dva ovládací prvky:
- Ovládací prvek textového pole s názvem
textBox1
. V aplikaci model Windows Forms byste měli nastavit její Multiline vlastnost natrue
hodnotu . - Ovládací prvek tlačítka s názvem
threadExampleBtn
. Příklad poskytuje obslužnou rutinu ,ThreadsExampleBtn_Click
pro událost tlačítkaClick
.
V každém případě obslužná rutina threadExampleBtn_Click
události volá metodu DoSomeWork
dvakrát. První volání se spustí synchronně a úspěšně. Druhé volání, protože běží asynchronně ve vlákně fondu vláken, se však pokusí aktualizovat uživatelské rozhraní z vlákna bez uživatelského rozhraní. Výsledkem je InvalidOperationException výjimka.
Aplikace 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;
}
Následující verze DoSomeWork
metody eliminuje výjimku v aplikaci 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; });
}
Aplikace 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
Následující verze DoSomeWork
metody eliminuje výjimku v aplikaci model Windows Forms.
private async void DoSomeWork(int milliseconds)
{
// simulate work
await Task.Delay(milliseconds);
// Report completion.
bool uiMarshal = textBox1.InvokeRequired;
String msg = String.Format("Some work completed in {0} ms. on {1}UI thread\n",
milliseconds, uiMarshal ? String.Empty : "non-");
lines.Add(msg);
if (uiMarshal) {
textBox1.Invoke(new Action(() => { textBox1.Lines = lines.ToArray(); }));
}
else {
textBox1.Lines = lines.ToArray();
}
}
Private Async Sub DoSomeWork(milliseconds As Integer)
' Simulate work.
Await Task.Delay(milliseconds)
' Report completion.
Dim uiMarshal As Boolean = TextBox1.InvokeRequired
Dim msg As String = String.Format("Some work completed in {0} ms. on {1}UI thread" + vbCrLf,
milliseconds, If(uiMarshal, String.Empty, "non-"))
lines.Add(msg)
If uiMarshal Then
TextBox1.Invoke(New Action(Sub() TextBox1.Lines = lines.ToArray()))
Else
TextBox1.Lines = lines.ToArray()
End If
End Sub
Změna kolekce při iteraci
Příkaz foreach
v jazyce C#, for...in
v jazyce F# nebo For Each
příkazu v jazyce Visual Basic slouží k iteraci členů kolekce a ke čtení nebo úpravě jednotlivých prvků. Nedá se ale použít k přidání nebo odebrání položek z kolekce. Tím dojde k výjimce InvalidOperationException se zprávou, která je podobná: "Kolekce byla změněna; Operace výčtu se nemusí spustit."
Následující příklad iteruje kolekci celých čísel se pokusí přidat čtverec každého celého čísla do kolekce. Příklad vyvolá InvalidOperationException první volání List<T>.Add metody.
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()
Výjimku můžete odstranit jedním ze dvou způsobů v závislosti na logice vaší aplikace:
Pokud musí být prvky přidány do kolekce při iteraci, můžete ji iterovat pomocí
for
příkazu (for..to
v jazyce F#) namístoforeach
,for...in
neboFor Each
. Následující příklad používá příkaz for k přidání čtverců čísel v kolekci do kolekce.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
Mějte na paměti, že před iterací kolekce je nutné určit počet iterací buď pomocí čítače uvnitř smyčky, která příslušnou smyčku odpovídajícím způsobem ukončí, iterací zpět, od
Count
- 1 do 0, nebo, jak je tomu v příkladu, přiřazením počtu prvků v matici k proměnné a jeho použitím k navázání horní hranice smyčky. V opačném případě, pokud je prvek přidán do kolekce při každé iteraci, nekonečné smyčky výsledky.Pokud během iterace není nutné do kolekce přidávat prvky, můžete je uložit do dočasné kolekce, kterou přidáte, když iterace kolekce skončí. Následující příklad používá tento přístup k přidání čtverců čísel v kolekci do dočasné kolekce a následné sloučení kolekcí do jednoho objektu pole.
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
Řazení pole nebo kolekce, jejichž objekty nelze porovnat
Metody řazení pro obecné účely, například metodu Array.Sort(Array) nebo metodu List<T>.Sort() , obvykle vyžadují, aby alespoň jeden z objektů byl seřazen implementací IComparable<T> nebo IComparable rozhraní. Pokud ne, kolekce nebo pole nelze řadit a metoda vyvolá InvalidOperationException výjimku. Následující příklad definuje Person
třídu, uloží dva Person
objekty do obecného List<T> objektu a pokusí se je seřadit. Jak ukazuje výstup z příkladu, volání List<T>.Sort() metody vyvolá 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()
Výjimku můžete odstranit některým ze tří způsobů:
Pokud můžete vlastnit typ, který se pokoušíte seřadit (to znamená, že pokud řídíte jeho zdrojový kód), můžete ho upravit tak, aby implementovala IComparable<T> rozhraní nebo IComparable rozhraní. To vyžaduje, abyste implementovali metodu IComparable<T>.CompareTo nebo metodu CompareTo . Přidání implementace rozhraní do existujícího typu není zásadní změnou.
Následující příklad používá tento přístup k poskytnutí IComparable<T> implementace třídy
Person
. Stále můžete volat metodu obecného řazení kolekce nebo pole a jak ukazuje výstup z příkladu, kolekce se úspěšně seřadí.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
Pokud nemůžete změnit zdrojový kód pro typ, který se pokoušíte seřadit, můžete definovat třídu řazení pro zvláštní účely, která implementuje IComparer<T> rozhraní. Můžete volat přetížení
Sort
metody, která obsahuje IComparer<T> parametr. Tento přístup je zvlášť užitečný, pokud chcete vyvinout specializovanou třídu řazení, která může řadit objekty na základě více kritérií.Následující příklad používá přístup vývojem vlastní
PersonComparer
třídy, která se používá k řazeníPerson
kolekcí. Pak předá instanci této třídy metodě 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("{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
Pokud nemůžete změnit zdrojový kód pro typ, který se pokoušíte seřadit, můžete vytvořit delegáta Comparison<T> pro provedení řazení. Podpis delegáta je
Function Comparison(Of T)(x As T, y As T) As Integer
int Comparison<T>(T x, T y)
Následující příklad používá přístup definováním
PersonComparison
metody, která odpovídá podpisu delegáta Comparison<T> . Potom tento delegát předá metodě 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("{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
Přetypování hodnoty Nullable<T> , která má hodnotu null na základní typ
Pokus o přetypování Nullable<T> hodnoty, která je null
na jeho základní typ vyvolá InvalidOperationException výjimku a zobrazí chybovou zprávu" Nullable objekt musí mít hodnotu.
Následující příklad vyvolá InvalidOperationException výjimku, když se pokusí iterovat pole, které obsahuje Nullable(Of Integer)
hodnotu.
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()
Zabránění výjimce:
- Nullable<T>.HasValue Pomocí vlastnosti vyberte pouze ty prvky, které nejsou
null
. - Voláním jednoho z Nullable<T>.GetValueOrDefault přetížení zadáte výchozí hodnotu pro
null
hodnotu.
V následujícím příkladu se vyhnete výjimce InvalidOperationException .
using System;
using System.Linq;
public class NullableEx2
{
public static void Main()
{
var queryResult = new int?[] { 1, 2, null, 4 };
var numbers = queryResult.Select(nullableInt => (int)nullableInt.GetValueOrDefault());
// Display list using Nullable<int>.HasValue.
foreach (var number in numbers)
Console.Write("{0} ", number);
Console.WriteLine();
numbers = queryResult.Select(nullableInt => (int) (nullableInt.HasValue ? nullableInt : -1));
// Display list using Nullable<int>.GetValueOrDefault.
foreach (var number in numbers)
Console.Write("{0} ", number);
Console.WriteLine();
}
}
// The example displays the following output:
// 1 2 0 4
// 1 2 -1 4
open System
open System.Linq
let queryResult = [| Nullable 1; Nullable 2; Nullable(); Nullable 4 |]
let numbers = queryResult.Select(fun nullableInt -> nullableInt.GetValueOrDefault())
// Display list using Nullable<int>.HasValue.
for number in numbers do
printf $"{number} "
printfn ""
let numbers2 = queryResult.Select(fun nullableInt -> if nullableInt.HasValue then nullableInt.Value else -1)
// Display list using Nullable<int>.GetValueOrDefault.
for number in numbers2 do
printf $"{number} "
printfn ""
// The example displays the following output:
// 1 2 0 4
// 1 2 -1 4
Imports System.Linq
Module Example14
Public Sub Main()
Dim queryResult = New Integer?() {1, 2, Nothing, 4}
Dim numbers = queryResult.Select(Function(nullableInt) _
CInt(nullableInt.GetValueOrDefault()))
' Display list.
For Each number In numbers
Console.Write("{0} ", number)
Next
Console.WriteLine()
' Use -1 to indicate a missing values.
numbers = queryResult.Select(Function(nullableInt) _
CInt(If(nullableInt.HasValue, nullableInt, -1)))
' Display list.
For Each number In numbers
Console.Write("{0} ", number)
Next
Console.WriteLine()
End Sub
End Module
' The example displays the following output:
' 1 2 0 4
' 1 2 -1 4
Volání metody System.Linq.Enumerable v prázdné kolekci
Funkce Enumerable.Aggregate, , Enumerable.Average, Enumerable.First, Enumerable.MaxEnumerable.Last, Enumerable.Min, Enumerable.Singlea Enumerable.SingleOrDefault metody provádějí operace v sekvenci a vrací jeden výsledek. Některá přetížení těchto metod vyvolá InvalidOperationException výjimku, pokud je sekvence prázdná, zatímco jiné přetížení vrátí null
. Metoda Enumerable.SingleOrDefault také vyvolá InvalidOperationException výjimku, pokud sekvence obsahuje více než jeden prvek.
Poznámka:
Většina metod, které vyvolává InvalidOperationException výjimku, jsou přetížení. Ujistěte se, že rozumíte chování přetížení, které zvolíte.
Následující tabulka uvádí zprávy o výjimce z InvalidOperationException objektů výjimky vyvolaných voláními některých System.Linq.Enumerable metod.
metoda | Zpráva |
---|---|
Aggregate Average Last Max Min |
Sekvence neobsahuje žádné prvky. |
First |
Sequence neobsahuje žádný odpovídající prvek. |
Single SingleOrDefault |
Sekvence obsahuje více než jeden odpovídající prvek. |
Způsob odstranění nebo zpracování výjimky závisí na předpokladech vaší aplikace a na konkrétní metodě, kterou voláte.
Pokud záměrně zavoláte jednu z těchto metod bez kontroly prázdné sekvence, předpokládáte, že sekvence není prázdná a že prázdná sekvence je neočekávaný výskyt. V takovém případě je vhodné výjimku zachytit nebo znovu načítat.
Pokud se nepodařilo zkontrolovat prázdnou sekvenci neúmyslně, můžete volat jedno z přetížení Enumerable.Any přetížení a určit, zda sekvence obsahuje nějaké prvky.
Tip
Enumerable.Any<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>) Volání metody před generováním sekvence může zvýšit výkon, pokud data, která se mají zpracovat, mohou obsahovat velký počet prvků nebo pokud operace, která generuje posloupnost, je nákladná.
Pokud jste volali metodu, například Enumerable.First, Enumerable.Lastnebo Enumerable.Single, můžete nahradit alternativní metodou, například Enumerable.FirstOrDefault, Enumerable.LastOrDefaultnebo Enumerable.SingleOrDefault, která vrátí výchozí hodnotu místo člena sekvence.
Příklady poskytují další podrobnosti.
Následující příklad používá metodu Enumerable.Average k výpočtu průměru sekvence, jejíž hodnoty jsou větší než 4. Vzhledem k tomu, že žádné hodnoty z původního pole překračují 4, nejsou do sekvence zahrnuty žádné hodnoty a metoda vyvolá InvalidOperationException výjimku.
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()
Výjimku lze odstranit voláním Any metody určit, zda sekvence obsahuje jakékoli prvky před voláním metody, která zpracuje posloupnost, jak ukazuje následující příklad.
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.
Metoda Enumerable.First vrátí první položku v sekvenci nebo první prvek v sekvenci, která splňuje zadanou podmínku. Pokud je sekvence prázdná a proto nemá první prvek, vyvolá InvalidOperationException výjimku.
V následujícím příkladu Enumerable.First<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>) metoda vyvolá InvalidOperationException výjimku, protože dbQueryResults pole neobsahuje prvek větší než 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()
Místo vrácení zadané nebo výchozí hodnoty můžete metodu Enumerable.FirstOrDefaultEnumerable.First volat. Pokud metoda nenajde první prvek v sekvenci, vrátí výchozí hodnotu pro tento datový typ. Výchozí hodnota je null
pro referenční typ, nula pro číselný datový typ a DateTime.MinValue typ DateTime .
Poznámka:
Interpretace hodnoty vrácené Enumerable.FirstOrDefault metodou je často složitá skutečností, že výchozí hodnota typu může být platnou hodnotou v sekvenci. V tomto případě zavoláte metodu Enumerable.Any , která určí, zda sekvence má platné členy před voláním Enumerable.First metody.
Následující příklad volá metodu Enumerable.FirstOrDefault<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>) , aby se zabránilo InvalidOperationException výjimce vyvolané v předchozím příkladu.
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.
Volání Enumerable.Single nebo Enumerable.SingleOrDefault v sekvenci bez jednoho prvku
Metoda Enumerable.Single vrátí jediný prvek sekvence nebo jediný prvek sekvence, která splňuje zadanou podmínku. Pokud v sekvenci nejsou žádné prvky nebo pokud existuje více než jeden prvek , metoda vyvolá InvalidOperationException výjimku.
Tuto metodu Enumerable.SingleOrDefault můžete použít k vrácení výchozí hodnoty místo vyvolání výjimky, pokud sekvence neobsahuje žádné prvky. Nicméně, Enumerable.SingleOrDefault metoda stále vyvolá InvalidOperationException výjimku, pokud sekvence obsahuje více než jeden prvek.
Následující tabulka uvádí zprávy o výjimce z InvalidOperationException objektů výjimky vyvolaných voláními metod Enumerable.Single a Enumerable.SingleOrDefault metod.
metoda | Zpráva |
---|---|
Single |
Sequence neobsahuje žádný odpovídající prvek. |
Single SingleOrDefault |
Sekvence obsahuje více než jeden odpovídající prvek. |
V následujícím příkladu Enumerable.Single vyvolá volání metody InvalidOperationException výjimku, protože sekvence nemá prvek větší než 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()
Následující příklad se pokusí zabránit výjimce InvalidOperationException vyvolané, když je sekvence prázdná místo volání Enumerable.SingleOrDefault metody. Vzhledem k tomu, že tato sekvence vrací více prvků, jejichž hodnota je větší než 2, vyvolá také InvalidOperationException výjimku.
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()
Enumerable.Single Volání metody předpokládá, že sekvence nebo sekvence, která splňuje zadaná kritéria, obsahuje pouze jeden prvek. Enumerable.SingleOrDefault předpokládá sekvenci s nulovým nebo jedním výsledkem, ale ne více. Pokud je tento předpoklad záměrný a tyto podmínky nejsou splněny, je vhodné výsledek znovu narůstání nebo zachycení výsledku InvalidOperationException . Jinak nebo pokud očekáváte, že dojde k neplatným podmínkám s určitou frekvencí, měli byste zvážit použití jiné Enumerable metody, například FirstOrDefault nebo Where.
Dynamický přístup k polím domény napříč aplikacemi
Běžné OpCodes.Ldflda zprostředkující instrukce (CIL) vyvolá InvalidOperationException výjimku, pokud objekt obsahující pole, jehož adresu se pokoušíte načíst, není v doméně aplikace, ve které je váš kód spuštěn. K adrese pole lze přistupovat pouze z domény aplikace, ve které se nachází.
Vyvolání výjimky InvalidOperationException
Výjimku byste měli vyvolat InvalidOperationException pouze v případě, že stav objektu z nějakého důvodu nepodporuje konkrétní volání metody. To znamená, že volání metody je platné za určitých okolností nebo kontextů, ale je neplatné v jiných.
Pokud selhání vyvolání metody je způsobeno neplatnými argumenty, pak ArgumentException nebo jedna z jeho odvozených tříd, ArgumentNullException nebo ArgumentOutOfRangeException, by měla být vyvolán místo.