我在一个有两个重载的类中有一个静态函数。除了一个或两个参数外,两个重载都完全相同。 string body
是我的函数中唯一必需的参数,你可以看到,rest是可选参数。但参数object y
和int 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 x
和object y
则相同。基本上有三个问题:
有没有告诉编译器“接受任何”(几乎不可能的任务,但仍然让我知道)?
如果没有,无论如何我可以创建一个单独的功能来处理这两种情况吗?像这样:
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
}
要解决此问题的其他解决方法吗?
编辑:
我无法重命名这两个功能。
我无法创建更多重载。这些组合不仅仅是可能的。我应该能够写Foo(string body, int x)
等等。如果参数超过10,则几乎不可能处理所有条件。简而言之,必须使用可选参数。
答案 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 = 0
或y = null
)会导致相同的结果。请注意,这种方法提供的优化选项较少,因为选择必须在运行时进行 - 而不是编译时(除非编译器能够区分它)。