【问题标题】:How to call overloaded methods having optional parameters without ambiguity for compiler?如何调用具有可选参数的重载方法而编译器没有歧义?
【发布时间】:2011-07-16 20:40:23
【问题描述】:

我在一个有两个重载的类中有一个静态函数。除了一个或两个参数之外,这两个重载都完全相同。 string body 是我的函数中您可以看到的唯一必要参数,其余是可选参数。但是参数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. 还有其他解决方法吗?

编辑:

  1. 我无法重命名这两个函数。

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

【问题讨论】:

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


    【解决方案1】:

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

    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】:

    如果您不确定是否安全。

    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 是参数本身。

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

    【讨论】:

    • 不,这不是解决方案。不仅仅是这些组合可能。我应该可以写Foo(string body, intx) 等。就这样。如果参数超过 10 个,几乎不可能处理所有条件!
    • 这与@hammar 的回答非常相似。
    • 一旦我们发现“超过 3 个参数”的详细信息,我们都编辑了我们的答案。
    【解决方案3】:

    提供一个包装器

    public static void Foo(字符串体)

    {

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

    }

    或类似的东西

    【讨论】:

      【解决方案4】:

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

      【讨论】:

      • 这是一种解决方法,但参数不会整齐地显示给用户。程序员应该明确知道这个参数是 int 类型,名称为“count”,该参数是 Question 对象等。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-13
      • 2013-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多