取这个界面:
interface ILogger
{
void Store(string payload);
}
ILogger 的此类实现:
class Logger : ILogger
{
void Store(string payload, bool swallowException = true)
{
...
}
}
我预计编译器会将 swallowException 识别为可选参数,从而满足接口(interface)的要求。相反,编译器会提示 Logger 没有实现接口(interface)成员 Store。
我尝试的另一件有趣的事情是显式实现接口(interface),如下所示:
class Logger : ILogger
{
void ILogger.Store(string payload, bool swallowException = true)
{
...
}
}
编译器发出警告“为参数‘swallowException’指定的默认值将无效,因为它适用于在不允许可选参数的上下文中使用的成员。”这似乎表明可选参数在某种程度上与显式接口(interface)定义不兼容,但为什么呢?
我可以通过使用两个单独的函数定义重载 Store 来解决这个问题(在可选参数存在之前的处理方式)。但是,我喜欢可选参数,因为它们的句法清晰,并且更希望它按照我期望的方式工作。
我知道可能有一个合理的(历史的或其他的)解释为什么会这样,但我似乎无法弄明白。
最佳答案
因为 C# 中的可选参数只是语法糖。
你的方法定义是
void Store(string payload, bool swallowException)
而不是
void Store(string payload)
这显然与界面不匹配。
默认参数的工作方式是编译器将默认值注入(inject)到方法的调用中。因此,如果您执行 Store(payload),编译器实际上会发出 Store(payload, true)。这对于理解默认参数非常重要——它是在调用者的编译时完成的。因此,如果您在不重新编译调用者的情况下更改被调用者中的默认参数,调用者仍将使用旧的默认参数。
这也解释了您收到的警告 - 因为默认值是由编译器显式传递的,并且您不能在不转换为接口(interface)的情况下调用接口(interface)的显式实现,您将没有机会永远使用默认值。
您实际上根本不想使用默认参数。简单地定义两个这样的方法:
void Store(string payload, bool swallowException)
{
// Do your job
}
void Store(string payload)
{
Store(payload, true);
}
这避免了上述两个问题 - 接口(interface)契约得到满足,默认参数现在是被调用者的一部分,而不是调用者。
就个人而言,我根本不在公共(public) API 方法中使用可选参数 - 当您决定在某个时候更改它们时,它们只是想引起麻烦。除非您可以确保它们将永远保持不变,否则不要使用它们。这同样适用于 const 和 enum - 两者也是在编译时而不是运行时确定的。
请记住,包含默认参数的原因是允许您不传递一些参数。这对于 COM API 调用(否则会要求您将所有不想作为 Type.Missing 传递的参数)或 null 值的事情有意义.即使使用 false 也只是在自找麻烦,因为有人认为更好的默认值是 true - 突然间,一些调用者使用 true 而一些 false,尽管所有人都认为他们使用的是“默认值”。对于像你这样的情况,我会使用 bool? 代替,默认值为 null(或 default(bool?),以哪个为准你比较喜欢)。在方法代码本身中,您可以轻松地在适当的位置处理默认值 - 例如,通过执行 swallowException.GetValueOrDefault(true)。
关于c# - 带有可选参数的接口(interface)实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30105563/
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere
我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"
我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)
两者都可以defsetup(options={})options.reverse_merge:size=>25,:velocity=>10end和defsetup(options={}){:size=>25,:velocity=>10}.merge(options)end在方法的参数中分配默认值。问题是:哪个更好?您更愿意使用哪一个?在性能、代码可读性或其他方面有什么不同吗?编辑:我无意中添加了bang(!)...并不是要询问nobang方法与bang方法之间的区别 最佳答案 我倾向于使用reverse_merge方法:option
我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden
我有一个只接受一个参数的方法:defmy_method(number)end如果使用number调用方法,我该如何引发错误??通常,我如何定义方法参数的条件?比如我想在调用的时候报错:my_method(1) 最佳答案 您可以添加guard在函数的开头,如果参数无效则引发异常。例如:defmy_method(number)failArgumentError,"Inputshouldbegreaterthanorequalto2"ifnumbereputse.messageend#=>Inputshouldbegreaterthano
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha
我没有找到太多关于如何执行此操作的信息,尽管有很多关于如何使用像这样的redirect_to将参数传递给重定向的建议:action=>'something',:controller=>'something'在我的应用程序中,我在路由文件中有以下内容match'profile'=>'User#show'我的表演Action是这样的defshow@user=User.find(params[:user])@title=@user.first_nameend重定向发生在同一个用户Controller中,就像这样defregister@title="Registration"@user=Use