次の方法で共有


メンバーのオーバーロード

メンバーのシグネチャには、そのメンバーの名前とパラメーター リストが含まれます。 各メンバーのシグネチャは、型内で一意であることが必要です。 パラメーター リストが異なる限り、メンバーは同じ名前を持つことができます。 ある型の 2 つ以上のメンバーが同じ種類のメンバー (メソッド、プロパティ、コンストラクターなど) であり、同じ名前と異なるパラメーター リストを持つ場合、そのメンバーはオーバーロードされていると言います。 たとえば、Array クラスには、2 つの CopyTo メソッドが含まれています。 1 つ目のメソッドは、配列と Int32 値を受け取り、2 つ目のメソッドは配列と Int64 値を受け取ります。

メモメモ

共通言語ランタイムの仕様で示されているように、メソッドの戻り値の型を変更しても、メソッドが一意になるわけではありません。戻り値の型だけが異なるオーバーロードを定義することはできません。

オーバーロードされたメンバーは、同じ機能のバリエーションを提供します。 たとえば、ある型が 2 つの CopyTo メンバーを持つときに、1 つ目のメンバーはデータを配列にコピーし、2 つ目のメンバーはデータをファイルにコピーするということは誤りです。 メンバーのオーバーロードの一般的な使用方法は、パラメーターをほとんどまたはまったく受け取らない使いやすいオーバーロードを用意することです。 これらのメンバーは、より強力なオーバーロードを呼び出しますが、正しく使用するには豊富な経験が必要となります。 使いやすいオーバーロードは、複雑なオーバーロードに既定値を渡すことで一般的なシナリオをサポートします。 たとえば、File クラスには、Open メソッドの複数のオーバーロードが用意されています。 単純なオーバーロード Open は、ファイル パスとファイル モードを受け取ります。 このオーバーロードは、パス、ファイル モード、ファイル アクセス、およびファイル共有の各パラメーターを受け取る Open オーバーロードを呼び出し、ファイル アクセス パラメーターとファイル共有パラメーターで共通に使用する既定値を提供します。 複雑なオーバーロードの柔軟性を必要としない開発者は、ファイル アクセスと共有モデルについて知らなくても、ファイルを開くことができます。

保守とバージョン管理を容易にするには、単純なオーバーロードで複雑なオーバーロードを使用してアクションを実行する必要があります。基になる機能は、複数の場所で実装しないようにします。

オーバーロードに関するガイドライン

次のガイドラインは、オーバーロードされたメンバーを適切にデザインできるようにするうえで役立ちます。

説明的なパラメーター名を使用して、単純なオーバーロードが使用する既定値を示すようにします。

このガイドラインは、Boolean パラメーターに最も当てはまります。 複雑なオーバーロードのパラメーター名では、対照的な状態やアクションを示すことによって、単純なオーバーロードから提供される既定値を示す必要があります。 たとえば、String クラスには、次のオーバーロードが用意されています。

Overloads Public Shared Function Compare( _
   ByVal strA As String, _
   ByVal strB As String _
) As Integer

Overloads Public Shared Function Compare( _
   ByVal strA As String, _
   ByVal strB As String, _
   ByVal ignoreCase As Boolean _
) As Integer
public static int Compare(
   string strA,
   string strB
);

public static int Compare(
   string strA,
   string strB,
   bool ignoreCase
);

2 つ目のオーバーロードには、ignoreCase という名前の Boolean パラメーターが用意されています。 これは、単純なオーバーロードが大文字と小文字を区別することを示しているため、大文字と小文字の区別を無視する場合にだけ、この複雑なオーバーロードを使用する必要があります。 通常、既定値は false にする必要があります。

オーバーロードのパラメーター名は任意で変更しないようにします。 あるオーバーロードのパラメーターが別のオーバーロードのパラメーターと同じ入力を表している場合、これらのパラメーターは同じ名前であることが必要です。

たとえば、次のようにしないでください。

Public Sub Write(message as String, stream as FileStream)
End Sub
Public Sub Write(line as String, file as FileStream, closeStream as Boolean)
End Sub
public void Write(string message, FileStream stream){}
public void Write(string line, FileStream file, bool closeStream){}
public:
    void Write(String^ message, FileStream^ stream){}
    void Write(String^ line, FileStream^ file, bool closeStream){}

これらのオーバーロードの正しい定義は次のとおりです。

Public Sub Write(message as String, stream as FileStream)
End Sub
Public Sub Write(message as String, stream as FileStream, _
    closeStream as Boolean)
End Sub
public void Write(string message, FileStream stream){}
public void Write(string message, FileStream stream, bool closeStream){}
public:
    void Write(String^ message, FileStream^ stream){}
    void Write(String^ message, FileStream^ stream, bool closeStream){}

オーバーロードされたメンバーのパラメーターの順序に一貫性を持たせます。 同じ名前のパラメーターは、すべてのオーバーロードで同じ位置に示す必要があります。

たとえば、次のようにしないでください。

Public Sub Write( message as String, stream as FileStream)
End Sub
Public Sub Write(stream as FileStream, message as String, _
    closeStream as Boolean)
End Sub
public void Write(string message, FileStream stream){}
public void Write(FileStream stream,  string message, bool closeStream){}
public:
    void Write(String^ message, FileStream^ stream){}
    void Write(FileStream^ stream, String^ message, bool closeStream){}

これらのオーバーロードの正しい定義は次のとおりです。

Public Sub Write(message as String, stream as FileStream)
End Sub
Public Sub Write(message as String, stream as FileStream, _
    closeStream as Boolean)
End Sub
public void Write(string message, FileStream stream){}
public void Write(string message, FileStream stream, bool closeStream){}
public:
    void Write(String^ message, FileStream^ stream){}
    void Write(String^ message, FileStream^ stream, bool closeStream){}

このガイドラインには、次の 2 つの制約があります。

  • オーバーロードが可変個引数リストを受け取る場合、このリストは最後のパラメーターにする必要があります。

  • オーバーロードが out パラメーターを受け取る場合、慣例により、これらは最後のパラメーターとして示す必要があります。

機能拡張が必要な場合は、最も長いオーバーロードだけを virtual (Visual Basic では Overridable) にします。 短いオーバーロードは、長いオーバーロードを単に呼び出すだけにする必要があります。

この方法のコード例を次に示します。

Public Sub Write(message as String, stream as FileStream)
    Me.Write(message, stream, false)
End Sub

Public Overridable Sub Write( _
    message as String, stream as FileStream, closeStream as Boolean)
    ' Do work here.
End Sub
public void Write(string message, FileStream stream)
{
    this.Write(message, stream, false);
}
public virtual void Write(string message, FileStream stream, bool closeStream)
{
    // Do work here.
}
public:
    void Write(String^ message, FileStream^ stream)
    {
        this->Write(message, stream, false);
    }

    virtual void Write(String^ message, FileStream^ stream, bool closeStream)
    {
        // Do work here.
    }

オーバーロードされたメンバーに対して、ref 修飾子または out 修飾子を使用しないでください。

たとえば、次のようにしないでください。

Public Sub Write(message as String,  count as Integer)


...


Public Sub Write(message as String, ByRef count as Integer)
public void Write(string message, int count)


...


public void Write(string message, out int count)
public:
    void Write(String^ message, int count)


...


void Write(String^ message, int% count)

一般に、オーバーロードされたメンバーに対してこれらの修飾子を使用しているデザインでは、デザイン上の深刻な問題が生じる可能性が高くなります。 メソッドで実行される正確なアクションの詳細を提供するために、いずれかのメンバーの名前を変更する必要があるかどうかを検討します。

省略可能な引数に対して、null (Visual Basic では Nothing) を渡すことができます。 メソッドが参照型の省略可能な引数を受け取る場合、既定値を使用する必要があることを示すために null を渡すことができます。 これにより、メンバーを呼び出す前に null をチェックする必要があるという問題を回避できます。

たとえば、次の例では、開発者は null をチェックする必要はありません。

Public Sub CopyFile (source as FileInfo, _
    destination as DirectoryInfo, _
    newName as string)

    If newName Is Nothing
        InternalCopyFile(source, destination) 
    Else
        InternalCopyFile(source, destination, newName)
    End If
End Sub
public void CopyFile (FileInfo source, DirectoryInfo destination, string newName)
{
    if (newName == null)
    {
        InternalCopyFile(source, destination);
    }
    else
    {
        InternalCopyFile(source, destination, newName);
    }
}
public:
    void CopyFile(FileInfo^ source, DirectoryInfo^ destination, String^ newName)
    {
        if (newName == nullptr)
       {
            InternalCopyFile(source, destination);
        }
        else
        {
            InternalCopyFile(source, destination, newName);
        }
    }

既定の引数でメンバーを定義するのではなく、メンバーのオーバーロードを使用します。 既定の引数は CLS 準拠ではないため、一部の言語からは使用できません。

メソッドのデザインに誤りのあるコード例を次に示します。

Public Sub Rotate (data as Matrix, Optional degrees as Integer = 180)
' Do rotation here
End Sub

このコードは、既定値を提供する単純なオーバーロードと共に、2 つのオーバーロードとして再デザインする必要があります。 正しいデザインを次のコード例に示します。

Overloads Public Sub Rotate (data as Matrix)
    Rotate(data, 180)
End Sub

Overloads Public Sub Rotate (data as Matrix, degrees as Integer)
' Do rotation here
End Sub

Portions Copyright 2005 Microsoft Corporation. All rights reserved.

Portions Copyright Addison-Wesley Corporation. All rights reserved.

設計ガイドラインの詳細についてを参照してください、「フレームワークの設計ガイドライン。規則、慣用句、および再利用可能なパターン。ネット ライブラリ」本クシシュトフ Cwalina、ブラッド エイブラムス、アスキー、2005 年発表しました。

参照

その他の技術情報

メンバーのデザインのガイドライン

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