gpt4 book ai didi

c# - 属性规范中奇怪的歧义(两个 using 指令)

转载 作者:可可西里 更新时间:2023-11-01 08:24:19 24 4
gpt4 key购买 nike

背景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'

Try it online!

我的问题是,为什么编译器在这种情况下不能选择正确的,而它在前面的两个示例中做得很好?

此行为是否符合 C# 语言规范?真的需要C#编译器在这里报错吗?

(当然我知道我可以通过明确地说出 [Alpha.Horse] 来解决它,所以我不是在要求那个“解决方案”。)

最佳答案

我们这里有两个概念混为一谈。


<强>1。编译器如何知道哪个类实现了属性

有一个简单的约定,属性可以通过类名或类名减去属性后缀来引用。因此,当您像这样将 [Horse] 注释添加到 someIdentifier 时,

[Horse]
someIdentifier

[Horse] 的实现必须是继承 Attribute 的类,该类称为 HorseAttributeHorse.

注意:有一个被广泛接受的约定,即所有实现属性的类都应该在类型名称后加上“Attribute”后缀。

<强>2。编译器如何知道代码引用的是哪种类型

当我们在代码中引用一个类型时,编译器会查找已加载到命名空间中的该类型的定义。如果命名空间中该类型有多个定义,则编译器不会采取任何措施来解决这种歧义,这取决于开发人员改进代码。编译器无法选择,因此引发 error CS1040 .

编译器不会进行任何语义或静态分析来推测编码人员的意图。它很难定义、执行成本高且容易出错。

此错误不会仅在查找属性的实现时抛出。


在您的编译示例中,第 2 点没有歧义,因此代码可以编译。

如果第 1 点的解析导致类型名称不明确,HorseHorseAttribute,则错误将来自第 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 {}

Try here

我同意在编译器处理来自一个命名空间的定义和从不同命名空间导入的定义的方式上存在混淆,而且确实存在不一致。

关于c# - 属性规范中奇怪的歧义(两个 using 指令),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57723624/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com