65.9K
CodeProject 正在变化。 阅读更多。
Home

在 C# 中实现默认参数的解决方法

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.17/5 (9投票s)

2006年10月11日

2分钟阅读

viewsIcon

29754

本文介绍了一种使用参数数组功能在 C# 中实现默认参数的变通解决方案。

引言

在学习 Java 时,C++ 中我为数不多的怀念之一就是默认参数功能。我一直希望 C# 能够重新引入此功能。不幸的是,在我开始学习 C# 的那天,我被告知 C# 中没有默认参数功能。我当时想,好吧,没有默认参数我们也能活下去。然而,在过去编写 C# 程序的几年里,我就是无法将默认参数从我的脑海中抹去。我不时地遇到一些情况,如果使用默认参数,就可以节省时间,甚至可能提高性能。所以,现在我正在尝试一些巧妙/笨拙的解决方案。

背景

如果你听说过“参数数组”或“可变参数”或“params”关键字,这个想法就很简单。C# 的“params”关键字允许你为方法指定可变数量的参数。我猜 99% 的 C# 代码编写者都使用过参数数组,因为我们非常好的朋友 Console.WriteLine(...) 本身就可以接受可变数量的参数。如果你想编写自己的接受参数数组的方法,你需要使用“params”关键字。 它的工作方式如下:

void PrintNumbers(params int[] numbers)
{
    Console.WriteLine("Count: {0}", numbers.Length);
    foreach (int n in numbers)
    {
        System.Console.WriteLine(numbers);
    }
}

void Test()
{
    PrintNumbers();
    PrintNumbers(1);
    PrintNumbers(2, 3);
    PrintNumbers(4, 5, 6);
    PrintNumbers(7, 8, 9, 10);
    // Basically you can go on like this forever,
    // and they all call exactly the same method above.
}
现在,参数数组意味着任意数量的参数(0 个或更多),而默认参数意味着 0 个或 1 个参数。 显然,默认参数只是参数数组的一种特殊情况。

实现

现在,让我们使用“params”关键字来获取默认参数。

class DefaultParameterTest
{
    private const int DEFAULT_ARG = 0;
    
    /// <summary>
    /// Purpose of this method...
    /// </summary>
    /// <param name="fixedArg">meaning of this parameter...</param>
    /// <param name="defaultArg">
    /// meaning of this parameter... 
    /// Note that this parameter is optional, and its default value is 0.
    /// </param>
    void TakeDefaultArgument(int fixedArg, params int[] defaultArg)
    {
        if (defaultArg.Length > 1)
            throw new ArgumentException("Too many arguments");

        int defaultArgValue;
        if (defaultArg.Length == 0)
            defaultArgValue = DEFAULT_ARG;
        else
            defaultArgValue = defaultArg[0];

        // use defaultArgValue for the following part of the method
        // ...
    }

    void Test()
    {
        // The following 3 calls achieve exactly the same result.

        // use default argument
        TakeDefaultArgument(9);
 
        // use user specified argument
        TakeDefaultArgument(9, 0); 

        // a wired way to pass in user defined argument, but legal
        TakeDefaultArgument(9, new int[] { 0 }); 


        // The following calls are invalid

        // compilation error
        TakeDefaultArgument(9, "0"); 

        // no compilation error or warning, but runtime exception
        TakeDefaultArgument(9, 0, 1); 
    }
}

我使用 int 进行说明,但基本上默认参数可以是任何类型。

关注点

这种变通方法有很多局限性和缺点。(否则它就不会被称为“变通方法”了)。以下是其中的一些:

“可默认”参数的数量仅限于一个,并且必须位于参数列表的末尾。

默认参数是类型安全的。但是,当你的默认参数本身的类型是数组时,它会变得非常棘手。(稍后可能会对此进行更多讨论。)

如果传入的参数过多,则不会出现编译错误,甚至不会出现警告。异常将在运行时抛出。这很痛苦,因为错误检查从编译时转移到运行时,效率更低且更危险。

你可以传入一个只有一个元素的数组,它仍然有效,尽管该方法期望 0 个或 1 个元素作为参数。 这是因为 C# 参数数组不仅可以接受单个或多个参数,还可以接受单个参数数组。

你无法在方法的签名中看到默认值。 我能想到的最好的解决方案是以明显的方式将默认值放在 XML 样式注释中。

因此,请注意:如果你想这样使用默认参数,请非常仔细地记录你的方法,以确保其他使用此方法的人都清楚地知道发生了什么。

历史

  • 2006 年 10 月 11 日 - 初稿。
© . All rights reserved.