共用方式為


HOW TO:處理查詢運算式中的例外狀況 (C# 程式設計手冊)

可以在查詢運算式的內容中呼叫任何方法。 但是,建議您避免在會導致副作用的查詢運算式中呼叫任何方法,副作用包括修改資料來源的內容或擲回例外狀況。 此範例顯示如何避免在查詢運算式中呼叫方法時引發例外狀況,而不違反一般的 .NET Framework 例外狀況處理方針。 這些方針會說明當您了解為何會在指定內容中擲回特定例外狀況時,是可以攔截該例外狀況。 如需詳細資訊,請參閱例外處理

最後的範例顯示在必須於查詢執行期間擲回例外狀況時,如何處理這些情況。

範例

下列範例顯示如何移動查詢運算式外的例外狀況處理程式碼。 這只有在方法不依賴查詢的任何區域變數時可行。

class ExceptionsOutsideQuery
{
    static void Main()
    {
        // DO THIS with a datasource that might
        // throw an exception. It is easier to deal with
        // outside of the query expression.
        IEnumerable<int> dataSource;
        try
        {
            dataSource = GetData();
        }
        catch (InvalidOperationException)
        {
            // Handle (or don't handle) the exception 
            // in the way that is appropriate for your application.
            Console.WriteLine("Invalid operation");
            goto Exit;
        }

        // If we get here, it is safe to proceed.
        var query = from i in dataSource
                    select i * i;

        foreach (var i in query)
            Console.WriteLine(i.ToString());

        //Keep the console window open in debug mode
        Exit:
        Console.WriteLine("Press any key to exit");
        Console.ReadKey();
    }

    // A data source that is very likely to throw an exception!
    static IEnumerable<int> GetData()
    {
        throw new InvalidOperationException();
    }
}

在某些情況下,對於從查詢內擲回之例外狀況最好的回應可能是立即停止執行查詢。 下列範例顯示如何處理從查詢主體內擲回的例外狀況。 假設 SomeMethodThatMightThrow 可能會造成需要停止執行查詢的例外狀況。

請注意,try 區塊包含 foreach 迴圈,但不包含查詢本身。 這是因為 foreach 迴圈是查詢實際執行的點。 如需詳細資訊,請參閱LINQ 查詢簡介 (C#)

class QueryThatThrows
{
    static void Main()
    {
        // Data source.
        string[] files = { "fileA.txt", "fileB.txt", "fileC.txt" };

        // Demonstration query that throws.
        var exceptionDemoQuery =
            from file in files
            let n = SomeMethodThatMightThrow(file)
            select n;

        // Runtime exceptions are thrown when query is executed.
        // Therefore they must be handled in the foreach loop.
        try
        {
            foreach (var item in exceptionDemoQuery)
            {
                Console.WriteLine("Processing {0}", item);
            }
        }

        // Catch whatever exception you expect to raise
        // and/or do any necessary cleanup in a finally block
        catch (InvalidOperationException e)
        {
            Console.WriteLine(e.Message);
        }

        //Keep the console window open in debug mode
        Console.WriteLine("Press any key to exit");
        Console.ReadKey();
    }

    // Not very useful as a general purpose method.
    static string SomeMethodThatMightThrow(string s)
    {
        if (s[4] == 'C')
            throw new InvalidOperationException();
        return @"C:\newFolder\" + s;
    }
}
/* Output:
    Processing C:\newFolder\fileA.txt
    Processing C:\newFolder\fileB.txt
    Operation is not valid due to the current state of the object.
 */

編譯程式碼

  • 建立以 .NET Framework 3.5 版為目標的 Visual Studio 專案。 根據預設,專案有 System.Core.dll 的參考,以及 System.Linq 命名空間的 using 指示詞。

  • 將程式碼複製至您的專案中。

  • 按 F5 編譯和執行程式。

按任何鍵離開主控台視窗。

請參閱

概念

LINQ 查詢運算式 (C# 程式設計手冊)