在一个方法重写改变params修饰符(Changing the params modifier in

2019-08-19 03:11发布

我知道,一个params改性剂(其在接通数组类型的一个参数为所谓的“参数阵列”)是特别不方法签名的一部分。 现在考虑这个例子:

class Giraffid
{
    public virtual void Eat(int[] leaves)
    {
        Console.WriteLine("G");
    }
}
class Okapi : Giraffid
{
    public override void Eat(params int[] leaves)
    {
        Console.WriteLine("O");
    }
}

这将编译没有警告。 然后他说:

var okapi = new Okapi();
okapi.Eat(2, 4, 6);  // will not compile! 

给出了一个错误( No overload for method 'Eat' takes 3 arguments )。

现在,我知道,编译器会将params修改到的应用System.ParamArrayAttribute到有问题的参数。 一般来说有在派生类使用一组不同的属性的应用属性之一收集到一个虚拟方法的参数,然后装潢“相应”参数在一个重写的方法也没有问题。

然而,编译器选择忽略我的params关键字默默。 相反,如果一个使得它倒过来,并适用params在基类中的参数Giraffid ,然后省略在覆盖关键字Okapi ,编译器选择装饰用这两种方法System.ParamArrayAttribute 。 我验证,当然这些东西与IL DASM。

我的问题:

这是记录在案的行为吗? 我已经通过C#语言规范彻底搜查,没有发现这个任何提及。

我可以说,至少在Visual Studio开发环境是混淆这一点。 当键入2, 4, 6在上述方法的调用,所述智能感知显示我void Okapi.Eat(params int[] leaves)中的尖端


为对比,我还试图实现一个接口的方法和改变存在/不存在的params接口和实现类,我试图限定委托类型和变化的params或不在任一委托类型定义或者其方法I组分配方法我的委托类型的变量。 在这种情况下,这是完全可能改变params -ness。

Answer 1:

编译器的行为是正确的,但是这是一个有点乱。 我宁愿这是至少一个警告。

这是不足为奇的,你不能找到其中的规范,它说这是正确的。 相关的位是:

形式M(A),其中M是一个方法组,和A是可选的参数列表,包括以下步骤中的一个方法调用的结合时处理:该组的候选方法方法调用被构造。 对于使用方法M组相关联的每个方法F,如果F是不通用,F是当M没有类型参数列表的候选,并且F是适用相对于A.

什么是“与方法M组相关的方法”? 嗯,首先,什么是方法组?

方法组,这是一组从一个成员查找所得的重载方法...

OK,那么什么是成员查找规则?

否则,该集合由T中名为N的所有可访问成员,包括继承的成员和名为N的对象可访问成员。 成员包括override修饰符被排除在集。

着重强调。

这里的实际结果是, 对于重载决议的目的,一个重写的方法被认为是最初声明的方法,而不是被覆盖方法。 这条规则是,不幸的是,侵犯在这种情况下:

virtual void M(int x, int y) { }
...
override void M(int y, int x) { } 
...
M(x = 1, y = 2);

重载决策从多个衍生版本使用的名称 。 这是一个事实,即命名的参数添加在游戏中非常晚的不幸后果。

简而言之:用于确定方法是否是“PARAMS”与否的目的,分析是在原始方法中完成,而不是在覆盖方法

这本来是很好,有编译器在这里给你一个警告。

可以说,至少在Visual Studio开发环境是混淆这

正确。 智能感知层总是显示用于重写的方法,而不是重写的方法的方法的信息。 研究表明,用户感到十分困惑时作了方法看起来好像他们是最初宣布方法,而不是压倒一切的方法。 ,当然,正如我前面提到的,那些是你要使用的命名参数的参数名。



Answer 2:

我认为它在1.6.6.4款C#规范的精选描述:

虚拟方法可以在派生类重写。 当一个实例方法声明包含override修饰符,该方法将覆盖具有相同签名的继承虚拟方法。 而虚拟方法声明引入了一个新方法,而重写方法声明中专门提供了一个新实现的方法使现有的继承虚方法。

根据是, virtual方法声明是非常重要的位置。 而virtual方法声明用于在每次调用该方法。 正确的override ñ实现(如果指定)都采取了在运行时,其中params无关的所有事情。

它可以通过简单的测试来证实:

class Giraffid
{
    public virtual void Eat(params int[] leaves)
    {
        Console.WriteLine("G");
    }
}
class Okapi : Giraffid
{
    public override void Eat(int[] leaves)
    {
        Console.WriteLine("O");
    }
}

该宣言

var o = new Okapi();
o.Eat(1, 2, 3);

工程100%的罚款。



文章来源: Changing the params modifier in a method override