背景在attribute specification , 有时有两种有效的方法来编写应用的属性。例如,如果属性类的名称为 HorseAttribute,您可以将该属性应用为 [HorseAttribute] 或只是 [Horse]。歧义可以用 @ 解决,例如 [@Horse]。
以下是一个有效的程序:
using System;
using Alpha;
using Beta;
namespace N
{
[Horse]
class C
{
}
}
namespace Alpha
{
// valid non-abstract attribute type with accessible constructor
class HorseAttribute : Attribute
{
}
}
namespace Beta
{
// any non-attribute type with that name
enum Horse
{
}
}
当我只编写 [Horse] 时,C# 编译器能够选择 Alpha.HorseAttribute。毕竟,Beta.Horse 类型完全不适合在属性规范中使用。
即使我交换了名称,C# 编译器也会知道该怎么做:
using System;
using Alpha;
using Beta;
namespace N
{
[Horse]
class C
{
}
}
namespace Alpha
{
// valid non-abstract attribute type with accessible constructor
class Horse : Attribute
{
}
}
namespace Beta
{
// any non-attribute type with that name
enum HorseAttribute
{
}
}
同样,编译器知道我想要 Alpha.Horse。
现在是我想问的代码。它与上面的相同,只是这两种类型现在具有相同的名称:
using System;
using Alpha;
using Beta;
namespace N
{
[Horse]
class C
{
}
}
namespace Alpha
{
// valid non-abstract attribute type with accessible constructor
class Horse : Attribute
{
}
}
namespace Beta
{
// any non-attribute type with that name
enum Horse
{
}
}
现在,C# 编译器拒绝构建,说:
error CS0104: 'Horse' is an ambiguous reference between 'Alpha.Horse' and 'Beta.Horse'
我的问题是,为什么编译器在这种情况下不能选择正确的,而它在前面的两个示例中做得很好?
此行为是否符合 C# 语言规范?真的需要C#编译器在这里报错吗?
(当然我知道我可以通过明确地说出 [Alpha.Horse] 来解决它,所以我不是在要求那个“解决方案”。)
最佳答案
我们这里有两个概念混为一谈。
<强>1。编译器如何知道哪个类实现了属性
有一个简单的约定,属性可以通过类名或类名减去属性后缀来引用。因此,当您像这样将 [Horse] 注释添加到 someIdentifier 时,
[Horse]
someIdentifier
[Horse] 的实现必须是继承 Attribute 的类,该类称为 HorseAttribute 或 Horse.
注意:有一个被广泛接受的约定,即所有实现属性的类都应该在类型名称后加上“Attribute”后缀。
<强>2。编译器如何知道代码引用的是哪种类型
当我们在代码中引用一个类型时,编译器会查找已加载到命名空间中的该类型的定义。如果命名空间中该类型有多个定义,则编译器不会采取任何措施来解决这种歧义,这取决于开发人员改进代码。编译器无法选择,因此引发 error CS1040 .
编译器不会进行任何语义或静态分析来推测编码人员的意图。它很难定义、执行成本高且容易出错。
此错误不会仅在查找属性的实现时抛出。
在您的编译示例中,第 2 点没有歧义,因此代码可以编译。
如果第 1 点的解析导致类型名称不明确,Horse 或 HorseAttribute,则错误将来自第 2 点。
编译器没有特别允许,例如我正在执行第 2 点以响应第 1 点,所以如果我在这种情况下有歧义,是否有针对第 1 点执行的第 2 点的特殊回退位置?
如果您考虑到特殊规定引入的额外复杂性和时间级别,您可能会接受要求代码作者采取一定程度的严格性会更好。
在我和其他人看来,要求代码避免这种歧义会导致代码更容易被他人和 future 的自己理解。这使得关于为什么的讨论有些没有实际意义,因为我们可以争辩说,编译器团队在这里所做的努力会使代码变得“更臭”,更难维护。
注意:进一步回答
当您考虑 Langauge specification 中的示例所展示的行为时
using System;
[AttributeUsage(AttributeTargets.All)]
public class X: Attribute
{}
[AttributeUsage(AttributeTargets.All)]
public class XAttribute: Attribute
{}
[X] // Error: ambiguity
class Class1 {}
[XAttribute] // Refers to XAttribute
class Class2 {}
[@X] // Refers to X
class Class3 {}
[@XAttribute] // Refers to XAttribute
class Class4 {}
我同意在编译器处理来自一个命名空间的定义和从不同命名空间导入的定义的方式上存在混淆,而且确实存在不一致。
强>强>关于c# - 属性规范中奇怪的歧义(两个 using 指令),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57723624/
我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah
刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr
我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2
我有这个html标记:我想得到这个:我如何使用Nokogiri做到这一点? 最佳答案 require'nokogiri'doc=Nokogiri::HTML('')您可以通过xpath删除所有属性:doc.xpath('//@*').remove或者,如果您需要做一些更复杂的事情,有时使用以下方法遍历所有元素会更容易:doc.traversedo|node|node.keys.eachdo|attribute|node.deleteattributeendend 关于ruby-Nokog
对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
我正在阅读一本关于Ruby的书,作者在编写类初始化定义时使用的形式与他在本书前几节中使用的形式略有不同。它看起来像这样:classTicketattr_accessor:venue,:datedefinitialize(venue,date)self.venue=venueself.date=dateendend在本书的前几节中,它的定义如下:classTicketattr_accessor:venue,:datedefinitialize(venue,date)@venue=venue@date=dateendend在第一个示例中使用setter方法与在第二个示例中使用实例变量之间是
我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha