방법: 쿼리 식의 예외 처리(C# 프로그래밍 가이드)

업데이트: 2007년 11월

쿼리 식의 컨텍스트에서 메서드를 호출할 수 있습니다. 그러나 데이터 소스의 내용 변경 및 예외 throw 등 의도하지 않은 결과가 발생할 수 있는 쿼리 식에서는 메서드를 호출하지 않는 것이 좋습니다. 이 예제에서는 예외 처리에 대한 일반적인 .NET Framework 지침을 위반하지 않고 쿼리 식에서 메서드를 호출할 때 예외가 발생하지 않도록 지정하는 방법을 보여 줍니다. 이러한 지침에서는 해당 컨텍스트에서 특정 예외가 throw되는 이유를 알고 있는 경우 해당 예외를 catch할 수 있다고 설명합니다. 자세한 내용은 예외 처리를 참조하십시오.

마지막 예제에서는 쿼리 실행 중에 예외를 throw해야 하는 경우를 처리하는 방법을 보여 줍니다.

예제

다음 예제에서는 예외 처리 코드를 쿼리 식 외부로 이동하는 방법을 보여 줍니다. 이러한 작업은 메서드가 쿼리에 대한 지역 변수에 종속되지 않는 경우에만 가능합니다.

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();
    }
}

경우에 따라 쿼리 내에서 throw되는 예외에 대한 가장 좋은 응답은 쿼리 실행을 즉시 중지하는 것입니다. 다음 예제에서는 쿼리 본문 내부에서 throw되는 예외를 처리하는 방법을 보여 줍니다. SomeMethodThatMightThrow에서 쿼리 실행을 중지하는 예외를 발생시킬 수 있다고 가정합니다.

try 블록에서는 쿼리 자체가 아니라 foreach 루프를 포함합니다. 이는 쿼리가 실제로 실행되는 지점에 foreach 루프가 있기 때문입니다. 자세한 내용은 LINQ 쿼리 소개를 참조하십시오.

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 claanup 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# 프로그래밍 가이드)