如何调用具有可选参数的重载方法而没有编译器的歧义?

时间:2011-07-16 20:40:23

标签: c# overloading optional-parameters argument-passing

我在一个有两个重载的类中有一个静态函数。除了一个或两个参数外,两个重载都完全相同。 string body是我的函数中唯一必需的参数,你可以看到,rest是可选参数。但参数object yint x不应该合在一起。所以我不得不写下两个重载。我提供了一个示例代码:

    public static void Foo(string body, string caption = "", int x = 0)
    {
        //leave it to me
    }

    public static void Foo(string body, string caption = "", object y = null)
    {
        //leave it to me
    }

现在当我想从其他类调用这个静态函数时,由于string body是唯一必需的参数,我有时会尝试编写:

ClassABC.Foo("hi there");

这给了我这个:The call is ambiguous between the following methods or properties。我知道为什么会发生这种情况,理想情况下解决方案是什么。但是我需要知道在C#中是否还可以做任何其他事情来解决这个问题。

显然,编译器对于选择要使用的函数感到困惑,但我不介意编译器会考虑任何两种情况,如果没有int xobject y则相同。基本上有三个问题:

  1. 有没有告诉编译器“接受任何”(几乎不可能的任务,但仍然让我知道)?

  2. 如果没有,无论如何我可以创建一个单独的功能来处理这两种情况吗?像这样:

    public static void Foo(string body, string caption = "", int x = 0 || object y = null) // the user should be able to pass only either of them!
    {
        //again, I can handle this no matter what
    }
    
  3. 要解决此问题的其他解决方法吗?

  4. 编辑:

    1. 我无法重命名这两个功能。

    2. 我无法创建更多重载。这些组合不仅仅是可能的。我应该能够写Foo(string body, int x)等等。如果参数超过10,则几乎不可能处理所有条件。简而言之,必须使用可选参数。

4 个答案:

答案 0 :(得分:5)

如果您不确定这样做是否安全。

public static void Foo(string body)
{
}

public static void Foo(string body, string caption)
{
}

public static void Foo(string body, string caption, int x)
{
}

public static void Foo(string body, string caption, object y)
{
}

编辑:由于你提到可能有10个左右的参数,你需要一个更通用的解决方案。

有一个带变量参数的选项。检查每个参数的类型并采取相应的行动:

public static void Foo(string body, param object[] the_rest_of_arguments)
{
}

如果两个参数具有相同的类型但功能不同(字符串标题,比如字符串作者),那么您还需要其他参数。您可以拥有一个将所有参数都作为成员的类。用户应该填充该类的对象并将该对象作为唯一参数传递:

public class FooArguments
{
    public string caption;
    public int x;
    public object y;
}

public static void Foo(string body, FooArguments the_rest_of_arguments)
{
}

您可以使用Dictionary<string,object>而不是新的类FooArguments,其中key是参数的名称,value是参数本身。

如果使用不恰当的参数组合调用函数,则只抛出异常。

答案 1 :(得分:5)

添加一个单独的重载来处理带有一个或两个参数的案例。

public static void Foo(string body, string caption = "")
{
} 

public static void Foo(string body, string caption, int x)
{
}

public static void Foo(string body, string caption, object y)
{
}

如果您需要处理任意参数组合,那么也许是时候将可选参数分组到自己的类中了:

public sealed class Options
{
    public string Caption { get; set; }
    public int X { get; set; }
    public object Y { get; set; }
}

public static void Foo(string body, Options options)
{

} 

答案 2 :(得分:1)

提供包装

public static void Foo(string body)

{

   public static void Foo(string body,  "", null);
  //leave it to me

}

或类似的东西

答案 3 :(得分:1)

如何仅使用GetType()实现第二个变量并检查作为第三个参数(如果有的话)传递的'对象'的实际类型?但是,假设跳过第三个参数(x = 0y = null)会导致相同的结果。请注意,这种方法提供的优化选项较少,因为选择必须在运行时进行 - 而不是编译时(除非编译器能够区分它)。