Jep*_*sen 12 c# compiler-errors custom-attributes .net-attributes
背景:在属性规范中,有时存在两种写入应用属性的有效方法。例如,如果属性类具有名称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
{
}
}
Run Code Online (Sandbox Code Playgroud)
Alpha.HorseAttribute我编写just时,C#编译器可以选择[Horse]。毕竟,类型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
{
}
}
Run Code Online (Sandbox Code Playgroud)
同样,编译器知道我要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
{
}
}
Run Code Online (Sandbox Code Playgroud)
现在,C#编译器拒绝构建,并说:
错误CS0104:“马”是“ Alpha.Horse”和“ Beta.Horse”之间的歧义引用
我的问题是,为什么编译器在前面的两个示例中做得很好,但在这种情况下为什么不能选择正确的代码呢?
此行为是否符合C#语言规范?实际上是否需要C#编译器在此处发出错误?
(当然,我知道我可以通过[Alpha.Horse]明确地说出来来解决它,因此我并不需要这种“解决方案”。)
Jod*_*ell 12
这里我们将两个概念混为一谈。
1.编译器如何知道哪个类实现属性
有一个简单的约定,可以用类名或不带属性后缀的类名来引用属性。因此,当您添加[Horse]注释时someIdentifier,
[Horse]
someIdentifier
Run Code Online (Sandbox Code Playgroud)
的实现[Horse]必须Attribute是称为HorseAttribute或的继承的类Horse。
注意:有一个广泛接受的约定,所有实现属性的类都应在类型名称后缀“ Attribute”。
2.编译器如何知道引用的是哪种类型的代码
当我们在代码中引用类型时,编译器将查找已加载到名称空间中的该类型的定义。如果在命名空间中有针对该类型的多个定义,则编译器将不采取任何措施解决这种歧义,这取决于开发人员是否要改进代码。编译器无法选择,因此引发错误CS1040。
编译器不会进行任何语义或静态分析来判断编码人员的意图。这将很难定义,执行成本高并且容易出错。
查找属性的实现时,不仅会引发此错误。
在您的编译示例中,第2点没有歧义,因此代码可以编译。
如果点1的解析导致类型名称不明确,Horse或者它HorseAttribute,则错误将来自点2。
编译器没有特殊的余地,例如,我正在响应点1执行点2,因此,如果我在这种情况下有歧义,那么对于点1s执行的点2s是否有特殊的后备位置?
如果您考虑到特殊规定所带来的额外复杂性和时间,您可能会接受,要求代码编写者有一定的严格度会更好。
在我和其他人看来,要求代码避免这种歧义会导致代码易于他人和自己的未来自己理解。这使我们开始讨论为什么有些争议,因为我们可以说编译器团队在这里付出的努力会使“更臭”的代码变得更难维护。
注意:答案之外
当您考虑Langauge规范中的示例所展示的行为时
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 {}
Run Code Online (Sandbox Code Playgroud)
我会同意,在编译器对待来自一个名称空间的定义和从不同名称空间导入的定义的处理方式上,确实存在混乱,甚至是不一致。
| 归档时间: |
|
| 查看次数: |
284 次 |
| 最近记录: |