成员重载

成员的签名包含成员的名称和参数列表。 每个成员签名在类型中必须是唯一的。 只要成员的参数列表不同,成员的名称可以相同。 如果类型的两个或多个成员是同类成员(方法、属性、构造函数等),它们具有相同的名称和不同的参数列表,则称该同类成员进行了重载。 例如,Array 类包含两个 CopyTo 方法。 第一个方法采用一个数组和一个 Int32 值,第二个方法采用一个数组和一个 Int64 值。

注意注意

如公共语言运行时规范所述,更改某个方法的返回类型并不能使该方法变得唯一。仅更改返回类型不能定义重载。

重载成员在同一功能上应有所不同。 例如,某个类型具有两个 CopyTo 成员,其中第一个成员向数组复制数据,第二个成员向文件复制数据,这样是不正确的。 对成员进行重载通常是为了提供带少量参数或不带参数且易于使用的重载。 这些成员调用功能更强大、要求经验丰富才能正确使用的重载。 易于使用的重载通过向复杂重载传递默认值,支持常见的方案。 例如,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
);

第二个重载提供一个名为 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){}

此准则有两项约束:

  • 如果重载采用变量参数列表,则该列表必须是最后一个参数。

  • 如果重载采用 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

此代码应重新设计为两个重载,由简单重载提供默认值。 下面的代码示例演示的设计是正确的。

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

部分版权所有 2005 Microsoft Corporation。 保留所有权利。

部分版权所有 Addison-Wesley Corporation。 保留所有权利。

设计指引的详细信息,请参阅"框架设计准则: 公约、 成语和可重复使用的模式。网络图书馆"书 Krzysztof Cwalina 和布拉德 · 艾布拉姆斯,2005年艾迪生 - 韦斯利,发表。

请参见

其他资源

成员设计准则

类库开发的设计准则