Jep*_*sen 37 c# language-lawyer member-access
好的,所以C#语言规范在规则上有一个特殊的部分(旧版链接),Color Color其中一个成员及其类型具有相同的名称.着名的大师Eric Lippert 曾在博客上发表过这篇文章.
我在这里要问的问题在某种意义上(不是)与常量枚举中的线程循环定义中提出的完全相同.如果你愿意,你可以去推荐其他问题.
现在我的问题.考虑以下代码:
namespace N
{
public enum Color
{
Green,
Brown,
Purple,
}
public class C1
{
public const Color Color = Color.Brown; // error CS0110 - WHY? Compiler confused by Color Color?
}
public class C2
{
public static readonly Color Color = Color.Brown; // fine
}
public class C3
{
public static Color Color = Color.Brown; // fine
}
public class C4
{
public Color Color = Color.Brown; // fine
}
}
Run Code Online (Sandbox Code Playgroud)
这里的要点是,在上面的每种情况中,最右边的标识符Color可以引用enum类型,也可以引用具有相同名称的类成员.但是Color Color上面提到的规则意味着我们应该看看member(Brown)是静态的还是非静态的.由于在这种情况下它是静态的,我们应该相应地解释Color.
我明显的主要问题是:为什么这不适用于const类型成员?这是无意的吗?
(显然,说N.Color.Brown(N是命名空间)"修复"它;我不是在问这个!)
附注:使用局部变量const,上述异常不存在:
public class C5
{
public Color Color;
void M()
{
const Color Color = Color.Brown; // works (no warning for not using local variable?)
}
}
public class C6
{
public Color Color;
void M()
{
const Color other = Color.Brown; // works (warning CS0219, 'other' not used)
}
}
Run Code Online (Sandbox Code Playgroud)
Eri*_*ert 27
这是一个错误.我无法在VS 2015的CTP 5中重现这个问题,我认为这个问题应该已经修复为Roslyn重写的一部分.但是,下面的评论者指出他们可以在CTP 6中重现它.所以我不确定这里发生了什么,这个bug是否已经修复.
在个人方面:我没有特别回想一下,当我在2010年首次报道时,我是否负责调查这个,但由于我在那时对圆度探测器做了大量工作,可能性非常好.
这远不是圆形探测器中唯一的错误; 如果存在嵌套泛型类型,那么它会变得相当混乱,而这些泛型类型又具有通用基类型,其类型参数涉及嵌套类型.
亚历克斯"不会修复"这个,我并不感到惊讶; 我花了很长时间重写了进行类循环检测的代码,这种变化被认为风险太大.所有这些工作都被罗斯林抨击了.
如果您有兴趣了解Color Color绑定代码如何在Roslyn中运行,请查看恰当命名的方法BindLeftOfPotentialColorColorMemberAccess- 我爱我一些描述性的方法名称 - 在Binder_Expressions.cs.
Dre*_*dan 13
1)它不适用于a,const因为它试图同时允许两个定义(枚举类型和类成员),因此它尝试将自身定义为自身的函数.
2)是无意的吗?有点.这是预期行为的意外后果.
基本上,这是微软承认的一个错误,但已经提交为"Will Not Fix",在此处记录了Connect .
我无法在任何地方找到5.0语言规范(文章或博客形式),但如果您有兴趣,可以在这里下载.我们感兴趣的是第161页第7.6.4节,成员访问,它是第一部分7.6.4.1,它与OP链接的部分相同(当时为7.5.4.1).
即使您的标识符现在具有两个单独的含义,您可以为成员和类型命名完全相同的名称(例如,颜色)这一事实是明确允许的.这是规范的语言:
7.6.4.1相同的简单名称和类型名称在EI表单的成员访问中,如果E是单个标识符,并且如果E作为简单名称(第7.6.2节)的含义是常量,字段,属性,局部变量,或与E的含义相同的类型的参数作为类型名称(§3.8),则允许E的两种可能含义.EI的两个可能含义从不含糊,因为在两种情况下我都必须是E类的成员.换句话说,该规则只允许访问静态成员和嵌套类型的E,否则会发生编译时错误.例如:
struct Color {
public static readonly Color White = new Color(...);
public static readonly Color Black = new Color(...);
public Color Complement() {...}
}
class A {
public Color Color; // Field Color of type Color
void F() {
Color = Color.Black; // References Color.Black static member
Color = Color.Complement(); // Invokes Complement() on Color field
}
static void G() {
Color c = Color.White; // References Color.White static member
}
}
Run Code Online (Sandbox Code Playgroud)
这是关键部分:
允许E的两种可能含义.EI的两个可能含义从不含糊,因为在两种情况下我都必须是E类的成员.换句话说,该规则只允许访问静态成员和嵌套类型的E,否则会发生编译时错误.
当你定义时Color Color = Color.Brown,会发生一些变化.由于I(Brown)在两种情况下都必须是E(Color)的成员(静态和非静态),因此该规则允许您访问两者,而不是由于当前(非静态)上下文而限制一个.但是,现在您已将其中一个上下文(您的非静态上下文)设为常量.因为它同时允许,它试图定义Color.Brown为两个枚举和类的成员,但有它取决于它自身的价值(你不能有一个问题const I = I + 1为例).
| 归档时间: |
|
| 查看次数: |
1334 次 |
| 最近记录: |