好的,回到基础。我想知道如何使用params
参数正确地重载方法。
这是我的情景。我从常规方法开始:
public void MyMethod(MyObject mo)
{
// method body
}
我为它创建了一个看起来像这样的重载:
public void MyMethod(MyObject mo, params string[] fields)
{
// new method body
MyMethod(mo);
}
明显的意图是MyMethod(new MyObject());
执行原始方法,MyMethod(new MyObject(), "field0"/*, etc...*/);
执行重载方法。但这不是我发现的情况。
实际发生的是MyMethod(new MyObject());
执行重载方法!
我不明白。在这种情况下,我将如何执行原始方法?
好的,所以这里是产生所描述行为的实际代码。
Class1Base.cs:
public class Class1Base
{
public virtual void MyMethod(MyObject ob)
{
Console.WriteLine("Called Class1Base");
}
}
的Class1.cs:
public class Class1 : Class1Base
{
public override void MyMethod(MyObject ob)
{
Console.WriteLine("called overridden method");
}
public void MyMethod(MyObject ob, params string[] fields)
{
Console.WriteLine("called OVERLOADED method");
}
}
MyObject.cs:
public class MyObject
{
public int Id { get; set; }
public string Description { get; set; }
}
然后,当我以这种方式执行此代码时:
var myClass = new Class1();
var myObject = new MyObject();
myClass.MyMethod(myObject);
myClass.MyMethod(null);
myClass.MyMethod(null, "string");
控制台显示:
called OVERLOADED method
called OVERLOADED method
called OVERLOADED method
我原以为它会显示:
called overridden method
called overridden method
called OVERLOADED method
为什么不呢?
答案 0 :(得分:5)
我认为你不是在告诉我们整个故事。 C#5规范的第7.3.5.2节(标题为“更好的功能成员”)部分说明:
•否则,如果MP以其正常形式适用且MQ具有 params数组,仅适用于其扩展形式,然后是MP 比MQ好。
这似乎就是这种情况,因为params
版本需要“扩展”为零长度数组。实际上,在本地尝试代码会产生调用非params
版本的预期结果。
更新:为了响应您的编辑,现在答案是明确的:您正在调用Class1
中的方法,这意味着在执行重载解析时,标记为{{1的方法最初不考虑。并且由于非覆盖方法适用(尽管以其扩展形式),这是所选择的方法。
具体而言,第7.6.5.1节部分阅读:
•候选方法集合被简化为仅包含来自的方法 派生类型最多:对于集合中的每个方法C.F,其中C是 声明方法F的类型,在基类中声明的所有方法 从集合中删除C的类型。
基类override
从候选集中排除,因此算法不会选择它。
这种行为背后的确切推理是避免出现“脆弱的基类”问题。假设我们有以下类层次结构:
MyMethod()
以下呼叫站点:
class A
{
}
class B : A
{
public void MyMethod(object o) { }
}
这显然会解决new B().MyMethod("a string");
MyMethod()
。但现在假设object
的创建者(可能是另一个团队的成员)决定A
也应该有A
。所以他们改变了他们的课程:
MyMethod()
现在想象如果我们不从基类型中排除方法会发生什么。您最初解析为class A
{
public void MyMethod(string s);
}
的电话会突然转为B.MyMethod()
(因为A.MyMethod()
是更好的匹配。)C#的设计者不想让其他人在一个完全不同的团队中,默默地改变代码的含义。
有关脆弱的基类问题的更多信息,Eric Lippert's (old) blog在该主题上有许多帖子。只是搜索一下。