gpt4 book ai didi

c# - C# 中的方法重载在使用 params 关键字时出现意外行为

转载 作者:行者123 更新时间:2023-12-02 22:01:00 25 4
gpt4 key购买 nike

好的,回到基础。我想知道如何使用 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

为什么不呢?

最佳答案

我认为您没有告诉我们整个故事。 C# 5 规范的第 7.3.5.2 节(标题为“更好的函数成员”)部分说道:

• Otherwise, if MP is applicable in its normal form and MQ has a params array and is applicable only in its expanded form, then MP is better than MQ.

这里似乎就是这种情况,因为 params 版本需要“扩展”为零长度数组。事实上,在本地尝试您的代码会产生调用非 params 版本的预期结果。

更新:为了响应您的编辑,现在答案很明确:您正在调用 Class1 中的方法,这意味着在执行重载解析时,方法标记为override 最初不被考虑。由于非覆盖方法是适用的(尽管以其扩展形式),因此选择了该方法。

具体来说,section 7.6.5.1部分阅读:

• The set of candidate methods is reduced to contain only methods from the most derived types: For each method C.F in the set, where C is the type in which the method F is declared, all methods declared in a base type of C are removed from the set.

基类MyMethod()被排除在候选集中,因此不会被算法选中。


此行为背后的确切原因是为了避免“脆弱的基类”问题的表现。假设我们有以下类层次结构:

class A
{
}

class B : A
{
public void MyMethod(object o) { }
}

以及以下调用站点:

new B().MyMethod("a string");

这显然会解析为采用对象MyMethod()。但是现在假设 A 的创建者(可能在另一个团队工作)决定 A 也应该有一个 MyMethod()。所以他们改变了他们的类(class):

class A
{
public void MyMethod(string s);
}

现在想象一下如果我们不从基类型中排除方法会发生什么。您最初解析为 B.MyMethod() 的调用突然解析为 A.MyMethod()(因为 string 是更好的匹配。)C# 的设计者不想让完全不同的团队中的另一个人默默地更改您的代码的含义。

有关脆弱基类问题的更多信息,Eric Lippert's (old) blog有许多关于该主题的帖子。稍微搜索一下。

关于c# - C# 中的方法重载在使用 params 关键字时出现意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16945541/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com