我知道 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!
给出错误(方法“Eat”没有重载需要 3 个参数)。
现在,我知道编译器将 params 修饰符转换为 System.ParamArrayAttribute 对相关参数的应用。通常,将一组属性应用于虚方法的参数,然后在派生类的重写方法中用一组不同的属性修饰“相应”参数是没有问题的。
然而,编译器选择默默地忽略我的 params 关键字。相反,如果反过来,将 params 应用于基类 Giraffid 中的参数,然后在 Okapi 的 override 中省略关键字,编译器选择用 System.ParamArrayAttribute 修饰两个方法。当然,我用 IL DASM 验证了这些事情。
我的问题:
这是记录在案的行为吗?我已经彻底搜索了 C# 语言规范,但没有找到任何提及。
我可以说至少 Visual Studio 开发环境对此感到困惑。在上述方法调用中键入 2, 4, 6 时,intellisense 会在提示中显示 void Okapi.Eat(params int[] leaves).
为了比较,我还尝试实现一个接口(interface)方法并更改接口(interface)和实现类中 params 的存在/不存在,我尝试定义一个委托(delegate)类型并更改 params 或不在委托(delegate)类型定义或其方法组中分配给我的委托(delegate)类型变量的方法。在这些情况下,完全可以更改 params-ness。
最佳答案
编译器的行为是正确的,但这有点困惑。我希望这至少是一个警告。
毫不奇怪,您在规范中找不到它说这是正确的地方。相关位是:
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 关联的方法”是什么?那么,首先,什么是方法组?
A method group, which is a set of overloaded methods resulting from a member lookup...
好的,那么成员查找规则是什么?
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.
添加了强调。
这里的实际结果是,出于重载决议的目的,被覆盖的方法被认为是最初声明的方法,而不是被覆盖. 不幸的是,在这种情况下违反了这条规则:
virtual void M(int x, int y) { }
...
override void M(int y, int x) { }
...
M(x = 1, y = 2);
重载解析使用来自更多派生 版本的名称。这是一个不幸的结果,因为命名参数是在游戏中很晚才添加的。
简而言之:为了确定一个方法是否为“params”,分析是在原始方法上进行的,而不是在覆盖方法上进行的。
如果编译器在这里给你一个警告就好了。
can say that at least the Visual Studio development environment is confused about this
正确。 IntelliSense 层始终显示重写方法的方法信息,而不是被重写的方法。研究表明,当方法看起来像是最初声明的方法而不是覆盖方法时,用户会感到困惑。当然,正如我之前提到的,这些是您要用于命名参数的参数名称。
关于c# - 在方法覆盖中更改 params 修饰符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27843804/
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我正在尝试设置一个puppet节点,但rubygems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由rubygems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby
如何正确创建Rails迁移,以便将表更改为MySQL中的MyISAM?目前是InnoDB。运行原始执行语句会更改表,但它不会更新db/schema.rb,因此当在测试环境中重新创建表时,它会返回到InnoDB并且我的全文搜索失败。我如何着手更改/添加迁移,以便将现有表修改为MyISAM并更新schema.rb,以便我的数据库和相应的测试数据库得到相应更新? 最佳答案 我没有找到执行此操作的好方法。您可以像有人建议的那样更改您的schema.rb,然后运行:rakedb:schema:load,但是,这将覆盖您的数据。我的做法是(假设
我想了解Ruby方法methods()是如何工作的。我尝试使用“ruby方法”在Google上搜索,但这不是我需要的。我也看过ruby-doc.org,但我没有找到这种方法。你能详细解释一下它是如何工作的或者给我一个链接吗?更新我用methods()方法做了实验,得到了这样的结果:'labrat'代码classFirstdeffirst_instance_mymethodenddefself.first_class_mymethodendendclassSecond使用类#returnsavailablemethodslistforclassandancestorsputsSeco
我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer
我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah
设置:狂欢ruby1.9.2高线(1.6.13)描述:我已经相当习惯在其他一些项目中使用highline,但已经有几个月没有使用它了。现在,在Ruby1.9.2上全新安装时,它似乎不允许在同一行回答提示。所以以前我会看到类似的东西:require"highline/import"ask"Whatisyourfavoritecolor?"并得到:Whatisyourfavoritecolor?|现在我看到类似的东西:Whatisyourfavoritecolor?|竖线(|)符号是我的终端光标。知道为什么会发生这种变化吗? 最佳答案
我试图使用yard记录一些Ruby代码,尽管我所做的正是所描述的here或here#@param[Integer]thenumberoftrials(>=0)#@param[Float]successprobabilityineachtrialdefinitialize(n,p)#initialize...end虽然我仍然得到这个奇怪的错误@paramtaghasunknownparametername:the@paramtaghasunknownparametername:success然后生成的html看起来很奇怪。我称yard为:$yarddoc-mmarkdown我做错了什么?