Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
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ýjimku InvalidOperationException vyvolají metody, 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 iterování.
- ResourceSet.GetString, pokud je sada prostředků uzavřena před voláním metody.
- XContainer.Add, pokud by přidání objektů vedlo 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 výjimka InvalidOperationException může být vyvolána v široké škále okolností, je důležité přečíst si zprávu vrácenou vlastností výjimky Message.
InvalidOperationException používá COR_E_INVALIDOPERATIONHRESULT, který má hodnotu 0x80131509.
Seznam počátečních hodnot vlastností pro instanci InvalidOperationExceptionnaleznete v konstruktoru InvalidOperationException.
Běžné příčiny výjimek typu InvalidOperationException
V následujících částech uvidíte, jaké běžné případy vedou k vyvolání výjimky InvalidOperationException v aplikaci. Způsob řešení problému závisí na konkrétní situaci. Nejčastěji ale dochází k výjimce z chyby vývojáře a InvalidOperationException výjimku lze očekávat a vyhnout.
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ého uživatelského rozhraní) pro .NET, jako jsou 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í). Při pokusu o přístup k prvku uživatelského rozhraní z jiného vlákna než vlákna uživatelského rozhraní se vyvolá InvalidOperationException. 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 přistupovat k tomuto objektu, protože ho vlastní jiné vlákno. |
| UWP aplikace | Aplikace se nazývá rozhraní, které bylo zařazeno pro jiné vlákno. |
| Aplikace Windows Forms | Křížová operace vlákna není platná: Ovládací prvek 'TextBox1' je přístupný z jiného vlákna, než ve kterém byl vytvořen. |
UI rozhraní pro .NET implementují dispečerský vzor, který zahrnuje metodu pro kontrolu, zda se volání člena prvku uživatelského rozhraní spouští na vlákně uživatelského rozhraní, a další metody pro naplánování tohoto volání ve stejném vlákně.
- V aplikacích WPF volejte metodu Dispatcher.CheckAccess, která určuje, jestli je metoda spuštěná ve vlákně bez uživatelského rozhraní. Vrátí
true, pokud metoda běží ve vlákně uživatelského rozhraní afalsejinak. Zavolejte jednu z přetížených metod Dispatcher.Invoke pro naplánování volání ve vlákně uživatelského rozhraní. - V aplikacích pro UPW zkontrolujte vlastnost CoreDispatcher.HasThreadAccess a zjistěte, jestli je metoda spuštěná ve vlákně bez uživatelského rozhraní. Voláním metody CoreDispatcher.RunAsync spusťte delegáta, který aktualizuje vlákno uživatelského rozhraní.
- V aplikacích Windows Forms použijte vlastnost Control.InvokeRequired k určení, jestli je metoda spuštěná ve vlákně bez uživatelského rozhraní. Zavolejte jedno z přetížení metody Control.Invoke pro provedení delegáta, který aktualizuje vlákno uživatelského rozhraní.
Následující příklady ilustrují výjimku InvalidOperationException, 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 Windows Forms byste měli nastavit jeho vlastnost Multiline natrue. - Tlačítko s názvem
threadExampleBtn. Příklad poskytuje obslužnou rutinuThreadsExampleBtn_Click, pro událostClicktlačítka.
V každém případě obslužná rutina události threadExampleBtn_Click volá DoSomeWork metodu dvakrát. První volání se spustí synchronně a úspěšně. Druhé volání, poněvadž běží asynchronně ve vlákně fondu, se však pokusí aktualizovat uživatelské rozhraní z vlákna, které není určeno pro uživatelské rozhraní. Výsledkem je výjimka InvalidOperationException.
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 metody DoSomeWork 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 pro 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 metody DoSomeWork eliminuje výjimku v aplikaci 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 její iteraci
Příkaz foreach v jazyce C#, for...in v jazyce F# nebo For Each 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ímto způsobem 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 prochází kolekci celých čísel a pokusí se přidat čtverec každého celého čísla do kolekce. Příklad vyvolá InvalidOperationException s prvním voláním metody 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()
Výjimku můžete odstranit jedním ze dvou způsobů v závislosti na logice vaší aplikace:
Pokud je nutné prvky přidat do kolekce při iteraci, můžete je iterovat indexem pomocí příkazu
for(for..tov jazyce F#) místoforeach,for...inneboFor 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($"{numbers[ctr]}^{square}"); Console.WriteLine($"Adding {square} to the collection..."); Console.WriteLine(); numbers.Add(square); } Console.WriteLine("Elements now in the collection: "); foreach (var number in numbers) Console.Write("{0} ", number); } } // The example displays the following output: // 1^1 // Adding 1 to the collection... // // 2^4 // Adding 4 to the collection... // // 3^9 // Adding 9 to the collection... // // 4^16 // Adding 16 to the collection... // // 5^25 // Adding 25 to the collection... // // Elements now in the collection: // 1 2 3 4 5 1 4 9 16 25open System open System.Collections.Generic let numbers = ResizeArray [| 1; 2; 3; 4; 5 |] let upperBound = numbers.Count - 1 for i = 0 to upperBound do let square = Math.Pow(numbers[i], 2) |> int printfn $"{numbers[i]}^{square}" printfn $"Adding {square} to the collection...\n" numbers.Add square printfn "Elements now in the collection: " for number in numbers do printf $"{number} " // The example displays the following output: // 1^1 // Adding 1 to the collection... // // 2^4 // Adding 4 to the collection... // // 3^9 // Adding 9 to the collection... // // 4^16 // Adding 16 to the collection... // // 5^25 // Adding 25 to the collection... // // Elements now in the collection: // 1 2 3 4 5 1 4 9 16 25Imports System.Collections.Generic Module Example7 Public Sub Main() Dim numbers As New List(Of Integer)({1, 2, 3, 4, 5}) Dim upperBound = numbers.Count - 1 For ctr As Integer = 0 To upperBound Dim square As Integer = CInt(Math.Pow(numbers(ctr), 2)) Console.WriteLine("{0}^{1}", numbers(ctr), square) Console.WriteLine("Adding {0} to the collection..." + vbCrLf, square) numbers.Add(square) Next Console.WriteLine("Elements now in the collection: ") For Each number In numbers Console.Write("{0} ", number) Next End Sub End Module ' The example displays the following output: ' 1^1 ' Adding 1 to the collection... ' ' 2^4 ' Adding 4 to the collection... ' ' 3^9 ' Adding 9 to the collection... ' ' 4^16 ' Adding 16 to the collection... ' ' 5^25 ' Adding 25 to the collection... ' ' Elements now in the collection: ' 1 2 3 4 5 1 4 9 16 25Mě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 tak, přiřazením počtu prvků v poli k proměnné a jeho použitím k navázání horní hranice smyčky. Pokud je prvek přidán do kolekce při každé iteraci, dojde k nekonečné smyčce.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 25open System open System.Collections.Generic let numbers = ResizeArray [| 1; 2; 3; 4; 5 |] let temp = ResizeArray() // Square each number and store it in a temporary collection. for number in numbers do let square = Math.Pow(number, 2) |> int temp.Add square // Combine the numbers into a single array. let combined = Array.zeroCreate<int> (numbers.Count + temp.Count) Array.Copy(numbers.ToArray(), 0, combined, 0, numbers.Count) Array.Copy(temp.ToArray(), 0, combined, numbers.Count, temp.Count) // Iterate the array. for value in combined do printf $"{value} " // The example displays the following output: // 1 2 3 4 5 1 4 9 16 25Imports System.Collections.Generic Module Example8 Public Sub Main() Dim numbers As New List(Of Integer)({1, 2, 3, 4, 5}) Dim temp As New List(Of Integer)() ' Square each number and store it in a temporary collection. For Each number In numbers Dim square As Integer = CInt(Math.Pow(number, 2)) temp.Add(square) Next ' Combine the numbers into a single array. Dim combined(numbers.Count + temp.Count - 1) As Integer Array.Copy(numbers.ToArray(), 0, combined, 0, numbers.Count) Array.Copy(temp.ToArray(), 0, combined, numbers.Count, temp.Count) ' Iterate the array. For Each value In combined Console.Write("{0} ", value) Next End Sub End Module ' The example displays the following output: ' 1 2 3 4 5 1 4 9 16 25
Řazení pole nebo kolekce, jejichž objekty nelze porovnat
Metody řazení pro obecné účely, jako je metoda Array.Sort(Array) nebo metoda List<T>.Sort(), obvykle vyžadují, aby alespoň jeden z objektů, které mají být seřazeny, implementoval rozhraní IComparable<T> nebo IComparable. Pokud ne, kolekce nebo pole nelze seř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í metody List<T>.Sort() 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($"{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 (tj. pokud řídíte jeho zdrojový kód), můžete ho upravit tak, aby implementovala IComparable<T> nebo rozhraní IComparable. To vyžaduje, abyste implementovali 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 pro poskytnutí implementace pro třídu IComparable<T>
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($"{person.FirstName} {person.LastName}"); } } // The example displays the following output: // Jane Doe // John Doeopen System type Person(firstName: string, lastName: string) = member val FirstName = firstName with get, set member val LastName = lastName with get, set interface IComparable<Person> with member this.CompareTo(other) = compare $"{this.LastName} {this.FirstName}" $"{other.LastName} {other.FirstName}" let people = ResizeArray() people.Add(new Person("John", "Doe")) people.Add(new Person("Jane", "Doe")) people.Sort() for person in people do printfn $"{person.FirstName} {person.LastName}" // The example displays the following output: // Jane Doe // John DoeImports System.Collections.Generic Public Class Person : Implements IComparable(Of Person) Public Sub New(fName As String, lName As String) FirstName = fName LastName = lName End Sub Public Property FirstName As String Public Property LastName As String Public Function CompareTo(other As Person) As Integer _ Implements IComparable(Of Person).CompareTo Return String.Format("{0} {1}", LastName, FirstName). CompareTo(String.Format("{0} {1}", other.LastName, other.FirstName)) End Function End Class Module Example10 Public Sub Main() Dim people As New List(Of Person)() people.Add(New Person("John", "Doe")) people.Add(New Person("Jane", "Doe")) people.Sort() For Each person In people Console.WriteLine("{0} {1}", person.FirstName, person.LastName) Next End Sub End Module ' The example displays the following output: ' Jane Doe ' John DoePokud 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 rozhraní IComparer<T>. Můžete zavolat přetíženou metodu
Sort, která zahrnuje parametr IComparer<T>. 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í třídy
PersonComparer, která se používá k řazeníPersonkolekcí. Potom předá instanci této třídy List<T>.Sort(IComparer<T>) metodě.using System; using System.Collections.Generic; public class Person3 { public Person3(String fName, String lName) { FirstName = fName; LastName = lName; } public String FirstName { get; set; } public String LastName { get; set; } } public class PersonComparer : IComparer<Person3> { public int Compare(Person3 x, Person3 y) { return String.Format("{0} {1}", x.LastName, x.FirstName). CompareTo(String.Format("{0} {1}", y.LastName, y.FirstName)); } } public class ListSortEx3 { public static void Main() { var people = new List<Person3>(); people.Add(new Person3("John", "Doe")); people.Add(new Person3("Jane", "Doe")); people.Sort(new PersonComparer()); foreach (var person in people) Console.WriteLine($"{person.FirstName} {person.LastName}"); } } // The example displays the following output: // Jane Doe // John Doeopen System open System.Collections.Generic type Person(firstName, lastName) = member val FirstName = firstName with get, set member val LastName = lastName with get, set type PersonComparer() = interface IComparer<Person> with member _.Compare(x: Person, y: Person) = $"{x.LastName} {x.FirstName}".CompareTo $"{y.LastName} {y.FirstName}" let people = ResizeArray() people.Add(Person("John", "Doe")) people.Add(Person("Jane", "Doe")) people.Sort(PersonComparer()) for person in people do printfn $"{person.FirstName} {person.LastName}" // The example displays the following output: // Jane Doe // John DoeImports System.Collections.Generic Public Class Person11 Public Sub New(fName As String, lName As String) FirstName = fName LastName = lName End Sub Public Property FirstName As String Public Property LastName As String End Class Public Class PersonComparer : Implements IComparer(Of Person11) Public Function Compare(x As Person11, y As Person11) As Integer _ Implements IComparer(Of Person11).Compare Return String.Format("{0} {1}", x.LastName, x.FirstName). CompareTo(String.Format("{0} {1}", y.LastName, y.FirstName)) End Function End Class Module Example11 Public Sub Main() Dim people As New List(Of Person11)() people.Add(New Person11("John", "Doe")) people.Add(New Person11("Jane", "Doe")) people.Sort(New PersonComparer()) For Each person In people Console.WriteLine("{0} {1}", person.FirstName, person.LastName) Next End Sub End Module ' The example displays the following output: ' Jane Doe ' John DoePokud nemůžete změnit zdrojový kód pro typ, který se pokoušíte seřadit, můžete vytvořit Comparison<T> delegáta pro řazení. Podpis delegáta je
Function Comparison(Of T)(x As T, y As T) As Integerint Comparison<T>(T x, T y)Následující příklad používá přístup definováním metody
PersonComparison, 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($"{person.FirstName} {person.LastName}"); } public static int PersonComparison(Person x, Person y) { return String.Format("{0} {1}", x.LastName, x.FirstName). CompareTo(String.Format("{0} {1}", y.LastName, y.FirstName)); } } // The example displays the following output: // Jane Doe // John Doeopen System open System.Collections.Generic type Person(firstName, lastName) = member val FirstName = firstName with get, set member val LastName = lastName with get, set let personComparison (x: Person) (y: Person) = $"{x.LastName} {x.FirstName}".CompareTo $"{y.LastName} {y.FirstName}" let people = ResizeArray() people.Add(Person("John", "Doe")) people.Add(Person("Jane", "Doe")) people.Sort personComparison for person in people do printfn $"{person.FirstName} {person.LastName}" // The example displays the following output: // Jane Doe // John DoeImports System.Collections.Generic Public Class Person12 Public Sub New(fName As String, lName As String) FirstName = fName LastName = lName End Sub Public Property FirstName As String Public Property LastName As String End Class Module Example12 Public Sub Main() Dim people As New List(Of Person12)() people.Add(New Person12("John", "Doe")) people.Add(New Person12("Jane", "Doe")) people.Sort(AddressOf PersonComparison) For Each person In people Console.WriteLine("{0} {1}", person.FirstName, person.LastName) Next End Sub Public Function PersonComparison(x As Person12, y As Person12) As Integer Return String.Format("{0} {1}", x.LastName, x.FirstName). CompareTo(String.Format("{0} {1}", y.LastName, y.FirstName)) End Function End Module ' The example displays the following output: ' Jane Doe ' John Doe
Přetypování hodnoty Nullable<T>, která má hodnotu null na základní typ
Při pokusu o přetypování hodnoty Nullable<T>, která je null, na svůj základní typ, vyvolá výjimku InvalidOperationException a zobrazí chybovou zprávu: "Objekt Nullable musí mít hodnotu.
Následující příklad vyvolá výjimku InvalidOperationException, 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:
- Pomocí vlastnosti Nullable<T>.HasValue vyberte pouze ty prvky, které nejsou
null. - Zavolejte jednu z přetížených funkcí Nullable<T>.GetValueOrDefault a zadejte výchozí hodnotu pro hodnotu
null.
Následující příklad provádí obě činnosti, aby se vyhnul 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
Metody Enumerable.Aggregate, Enumerable.Average, Enumerable.First, Enumerable.Last, Enumerable.Max, Enumerable.Min, Enumerable.Singlea Enumerable.SingleOrDefault provádějí operace v posloupnosti a vrací jeden výsledek. Některá přetížení těchto metod vyvolá výjimku InvalidOperationException, pokud je sekvence prázdná, zatímco jiné přetížení vrací null. Metoda Enumerable.SingleOrDefault také vyvolá výjimku InvalidOperationException, pokud sekvence obsahuje více než jeden prvek.
Poznámka:
Většina metod, které vyvolávají výjimku InvalidOperationException, 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 objektů výjimky InvalidOperationException vyvolaných voláními některých System.Linq.Enumerable metod.
| Metoda | Zpráva |
|---|---|
Aggregate Average Last Max Min |
Sequence neobsahuje žádné prvky |
First |
Sequence neobsahuje žádný odpovídající prvek |
Single SingleOrDefault |
Sequence 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 přehodit.
Pokud jste neúmyslně nezkontrolovali prázdnou sekvenci, můžete volat jednu z přetížených variant funkce Enumerable.Any pro zjištění, zda sekvence obsahuje nějaké prvky.
Návod
Volání metody Enumerable.Any<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>) před generováním sekvence může zlepšit výkon, pokud data, která se mají zpracovat, může obsahovat velký počet prvků nebo pokud operace, která generuje posloupnost, je nákladná.
Pokud jste volali metodu, jako je Enumerable.First, Enumerable.Lastnebo Enumerable.Single, můžete nahradit alternativní metodu, například Enumerable.FirstOrDefault, Enumerable.LastOrDefaultnebo Enumerable.SingleOrDefault, která místo člena sekvence vrátí výchozí hodnotu.
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 eliminovat voláním metody Any, která má určit, zda posloupnost obsahuje nějaké prvky, před voláním metody, která zpracovává 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: {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á výjimku InvalidOperationException.
V následujícím příkladu vyvolá metoda Enumerable.First<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>) výjimku InvalidOperationException, protože pole dbQueryResults 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 {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 Enumerable.FirstOrDefault můžete volat metodu Enumerable.First a vrátit zadanou nebo výchozí hodnotu. Pokud metoda nenajde první prvek v sekvenci, vrátí výchozí hodnotu pro tento datový typ. Výchozí hodnota je null pro typ odkazu, nula pro číselný datový typ a DateTime.MinValue pro typ DateTime.
Poznámka:
Interpretace hodnoty vrácené metodou Enumerable.FirstOrDefault 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 metody Enumerable.First.
Následující příklad volá metodu Enumerable.FirstOrDefault<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>), aby zabránil výjimce InvalidOperationException 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 {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.
Volejte Enumerable.Single nebo Enumerable.SingleOrDefault na sekvenci, která neobsahuje jediný prvek.
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.
Metodu Enumerable.SingleOrDefault můžete použít k vrácení výchozí hodnoty místo vyvolání výjimky v případě, že sekvence neobsahuje žádné prvky. Metoda Enumerable.SingleOrDefault však přesto vyvolá výjimku InvalidOperationException, pokud sekvence obsahuje více než jeden prvek.
Následující tabulka uvádí zprávy o výjimce z objektů výjimky InvalidOperationException vyvolaných voláními Enumerable.Single a Enumerable.SingleOrDefault metod.
| Metoda | Zpráva |
|---|---|
Single |
Sequence neobsahuje žádný odpovídající prvek |
Single SingleOrDefault |
Sequence obsahuje více než jeden odpovídající prvek |
V následujícím příkladu vyvolá volání metody Enumerable.Single výjimku InvalidOperationException, 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($"{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()
Následující příklad se pokusí zabránit vyvolání výjimky InvalidOperationException, když je sekvence prázdná, tím, že místo toho zavolá metodu Enumerable.SingleOrDefault. Vzhledem k tomu, že tato sekvence vrací více prvků, jejichž hodnota je větší než 2, vyvolá také výjimku InvalidOperationException.
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()
Volání Enumerable.Single metoda 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 už ne. Pokud je tento předpoklad záměrný a tyto podmínky nejsou splněny, je vhodné opětovné vyvolání nebo zachycení výsledného 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é metody Enumerable, například FirstOrDefault nebo Where.
Dynamický přístup k polím domény napříč aplikacemi
Instrukce OpCodes.Ldflda společný zprostředkující jazyk (CIL) vyvolá výjimku InvalidOperationException, pokud objekt obsahující pole, jehož adresu se pokoušíte načíst, není v doméně aplikace, ve které je 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 InvalidOperationException byste měli vyvolat 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 je selhání vyvolání metody způsobené neplatnými argumenty, měla by být místo toho vyvolán ArgumentException nebo jedna z jeho odvozených tříd, ArgumentNullException nebo ArgumentOutOfRangeException.