在方法覆盖更改params修饰符 [英] Changing the params modifier in a method override

查看:181
本文介绍了在方法覆盖更改params修饰符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道,一个 PARAMS 修改(这将会在数组类型的一个参数到一个所谓的参数数组)是不明确的部分方法签名。现在考虑这个例子:

I'm aware that a params modifier (which turns in one parameter of array type into a so-called "parameter array") is specifically not a part of the method signature. Now consider this example:

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

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

This compiles with no warnings. Then saying:

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



给出了一个错误(无过载方法'吃'3个参数)。

现在,我知道,编译器会将 PARAMS 修改成一个应用程序的 System.ParamArrayAttribute 到相应的参数。一般来说有申请属性的一个集合到一个虚拟方法的参数,然后装饰在压倒一切的方法,在相对应的参数有不同的属性派生类中没有任何问题。

Now, I know that the compiler translates the params modifier into an application of the System.ParamArrayAttribute onto the parameter in question. In general there's no problem in applying one collection of attributes to a parameter of a virtual method, and then decorating the "corresponding" parameter in an overriding method in a derived class with a different set of attributes.

然而,编译器选择忽略我的 PARAMS 关键字默默。反之,如果一个使得它倒过来,并适用 PARAMS 来在基类中的参数 Giraffid ,和然后省略了覆盖关键字在霍加皮,编译器会选择装饰的两个的方法与 System.ParamArrayAttribute 。我核实,当然这些东西与IL DASM,

Yet the compiler chooses to ignore my params keyword silently. Conversely, if one makes it the other way round, and applies params to the parameter in the base class Giraffid, and then omits the keyword in the override in Okapi, the compiler chooses to decorate both methods with the System.ParamArrayAttribute. I verified these things with IL DASM, of course.

我的问题:

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

我可以说,至少在Visual Studio开发环境是困惑这个。当键入 2,4,6 在上面的方法调用,在智能感知显示我无效Okapi.Eat(PARAMS INT []叶子)在提示

I can say that at least the Visual Studio development environment is confused about this. When typing the 2, 4, 6 in the above method call, the intellisense shows me void Okapi.Eat(params int[] leaves) in a tip.

有关对比,我也试过实现一个接口方法和不断变化的存在/不存在 PARAMS 的接口和实现类,我试图定义一个委托类型,改变 PARAMS 或没有任何委托类型定义或者其方法I组分配给我的委托类型的变量的方法。在这种情况下,这是完全可能改变 PARAMS -ness。

For comparision, I also tried implementing an interface method and changing the presence/absence of params in interface and implementing class, and I tried defining a delegate type and changing params or not in either the delegate type definition or the method whose method group I assigned to a variable of my delegate type. In these cases it was perfectly possible to change params-ness.

推荐答案

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

The compiler's behaviour is correct, but this is a bit of a mess. I would have preferred this to be at least a warning.

这是不足为奇的,你找不到的地方在规范它说,这是正确的。相关位是:

It is unsurprising that you can't find where in the spec it says this is correct. The relevant bits are:

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

The binding-time processing of a method invocation of the form M(A), where M is a method group, and A is an optional argument-list, consists of the following steps: The set of candidate methods for the method invocation is constructed. For each method F associated with the method group M, if F is non-generic, F is a candidate when M has no type argument list, and F is applicable with respect to A.

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

What are the "methods associated with the method group M"? Well, first off, what is a method group?

方法组,这是一组由成员查找产生的重载方法。 ..

A method group, which is a set of overloaded methods resulting from a member lookup...

确定,因此哪些成员查找规则?

OK, so what are the member lookup rules?

否则,该集由T中名为N的所有可访问的成员,包括继承的成员并命名为N的对象可访问成员。

Otherwise, the set consists of all accessible members named N in T, including inherited members and the accessible members named N in object. Members that include an override modifier are excluded from the set.

着重强调的成员,其中包括一个override修饰符被排除在集。

Emphasis added.

下面的实际结果是,作为重载决议的目的,一个重写的方法被认为是是的最初宣布,而不是方法是覆盖这条规则是,不幸的是,违反了在这种情况下:

The practical upshot here is that for the purpose of overload resolution, an overridden method is considered to be the method that was originally declared, not the method that was overriding. This rule is, unfortunately, violated in this case:

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



重载使用的名称的距离的更多衍生版本。这是一个事实,即命名参数添加在游戏很晚了不幸的后果。

Overload resolution uses the names from the more derived version. This is an unfortunate consequence of the fact that named arguments were added very late in the game.

在短:用于确定一个方法是否是PARAMS与否的目的,分析是在原始方法的,不这样做上的重写方法的。

In short: for the purposes of determining whether a method is "params" or not, the analysis is done on the original method, not on the overriding method.

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

It would have been nice had the compiler given you a warning here.

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

can say that at least the Visual Studio development environment is confused about this

正确的。智能感知层始终显示压倒一切的方法,而不是覆盖方法方法信息。研究表明,用户发现它令人困惑的时候作了方法看起来好像他们是最初宣布的方法,而不是压倒一切的方法。当然,正如我前面提到的,那些是你要使用的命名参数的参数名。

Correct. The IntelliSense layer always displays the method information for the overriding method, not the overridden method. Research showed that users found it confusing when methods were made to look as though they were the originally declaring method, not the overriding method. And of course, as I mentioned before, those are the parameter names you're going to use for named arguments.

这篇关于在方法覆盖更改params修饰符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆