次の方法で共有


例外とパフォーマンス

更新 : 2007 年 11 月

例外をスローすると、パフォーマンスに悪影響が及ぶことがあります。定期的に失敗するコードでは、パフォーマンスの問題を最小にできるデザイン パターンを使用する必要があります。ここでは、例外がパフォーマンスに著しく影響する可能性がある場合に有効な 2 つのデザイン パターンについて説明します。

例外がパフォーマンスに悪影響を及ぼす可能性があるため、エラー コードは使用しないでください。

パフォーマンスの問題を最小にするデザインを使用してください。ここでは、2 つのパターンについて説明します。

一般的なシナリオで例外をスローする可能性があるメンバに対しては、例外に関連するパフォーマンスの問題を回避するために Tester-Doer パターンの使用を検討してください。

Tester-Doer パターンでは、例外をスローする可能性がある呼び出しを Tester と Doer の 2 つの部分に分割します。Doer に例外をスローさせるような状態がないかを Tester がテストします。このテストは、例外をスローするコードの直前に挿入され、これによって例外が防止されます。

次のコード例は、このパターンの Doer の部分を示しています。この例には、null (Visual Basic の場合は Nothing) 値が渡されると例外をスローするメソッドが含まれています。このメソッドを頻繁に呼び出すと、パフォーマンスに悪影響を及ぼす可能性があります。

Public Class Doer

    ' Method that can potential throw exceptions often.
    Public Shared Sub ProcessMessage(ByVal message As String)
        If (message = Nothing) Then
            Throw New ArgumentNullException("message")
        End If
    End Sub

    ' Other methods...
End Class
public class Doer
{
    // Method that can potential throw exceptions often.
    public static void ProcessMessage(string message)
    {
        if (message == null)
        {
            throw new ArgumentNullException("message");
        }
    }
    // Other methods...
}

次のコード例は、このパターンの Tester の部分を示しています。このメソッドは、Doer (ProcessMessage) が例外をスローする場合に、テストを行って Doer の呼び出しを防ぎます。

Public Class Tester

    Public Shared Sub TesterDoer(ByVal messages As ICollection(Of String))
        For Each message As String In messages
            ' Test to ensure that the call 
            ' won't cause the exception.
            If (Not (message) Is Nothing) Then
                Doer.ProcessMessage(message)
            End If
        Next
    End Sub
End Class
public class Tester
{
    public static void TesterDoer(ICollection<string> messages)
    {
        foreach (string message in messages)
        {
            // Test to ensure that the call
            // won't cause the exception.
            if (message != null)
            {
                Doer.ProcessMessage(message);
            }
        }
    }
}

テストが変更可能なオブジェクトを伴うマルチスレッド アプリケーションでこのパターンを使用する場合は、潜在的な競合状態に対処する必要があります。スレッドでは、テストを行ってから Doer を実行するまでの間に、変更可能なオブジェクトの状態が変更されることがあります。この問題に対処するには、スレッドの同期手法を使用します。

一般的なシナリオで例外をスローする可能性があるメンバに対しては、例外に関連するパフォーマンスの問題を回避するために TryParse パターンの使用を検討してください。

TryParse パターンを実装するには、2 つの異なるメソッドを使用して、一般的なシナリオで例外をスローする可能性がある操作を実行します。1 つは X メソッドで、操作を実行し、必要に応じて例外をスローします。もう 1 つは TryX メソッドで、例外はスローしませんが、代わりに成功または失敗を示す Boolean 値を返します。TryX の呼び出しが成功したときに返されるデータは、out (Visual Basic の場合は ByRef) パラメータを使用して返されます。Parse メソッドと TryParse メソッドは、このパターンの例です。

TryParse パターンを使用する各メンバに例外スロー メンバを提供してください。

TryX メソッドを使用する場合は、out パラメータについて理解する必要があるため、このメソッドのみを提供することはほとんどの場合正しいデザインとは言えません。また、一般的なシナリオでは、パフォーマンスへの例外の影響は問題になりません。一般的なシナリオでは、使いやすいメソッドを提供する必要があります。

Portions Copyright 2005 Microsoft Corporation.All rights reserved.

Portions Copyright Addison-Wesley Corporation.All rights reserved.

デザイン ガイドラインの詳細については、2005 年に Addison-Wesley から出版されている Krzysztof Cwalina、Brad Abrams 共著の『Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries』を参照してください。

参照

その他の技術情報

クラス ライブラリ開発のデザイン ガイドライン

例外のデザインのガイドライン