为什么类成员的名称不能与其中一个嵌套类相同?

时间:2011-01-19 02:45:41

标签: c# properties conflict nested-class

或者为什么以下不可能:

class Material
{
    class Keys
    {
        ...
    }

    Material.Keys Keys { get; set; } // Illegal
}

我没有看到任何可能的歧义。按实例访问时,返回属性。静态访问时,返回类。或者我错过了什么?

我不是要求“修复”(我知道我可以用不同的名称命名,比如MaterialKeys之类的东西),但更多的是这个限制背后的技术原因。

5 个答案:

答案 0 :(得分:12)

但想象你有这个:

class Material
{
    class Keys
    {
        ...
    }

    static Material.Keys Keys = new Keys();
}

现在两者都处于“静态”范围。现在,编译器可以在所有情况下消除歧义吗?如果没有,则不允许这样做。

我认为消歧可能适用于静态字段/属性/方法,而不适用于实例成员。或者相反。如果是这种情况,您是否希望语言规范允许实例成员与内部类具有相同的名称,但是不允许它用于静态?那只会令人困惑。

但是,无论如何,让一个成员匹配内部类的名称是非常令人困惑的。

答案 1 :(得分:11)

“任何不模糊的东西都应该是合法的”绝对不是C#语言的设计原则。 C#语言旨在成为“质量坑”的语言;也就是说,语言规则应该让你进入一个充满清晰正确代码的坑,你必须努力爬出坑,把它变成错误的代码。在大多数情况下,“任何不模糊的东西应该是合法的”这一观点直接反对“质量坑”语言的概念。

此外,您需要向我提供不执行功能的理由的想法是倒退的。我们永远不需要为执行功能提供理由。相反,提出的功能必须通过证明它们的好处超过其巨大的成本来证明。功能非常昂贵,我们的预算有限;我们必须只做最好的功能,以便为我们的客户带来好处。

您提出的功能可以轻松生成易碎且令人困惑的代码;它有助于使C#成为一个“绝望的陷阱”而不是“质量陷阱”的语言。增加脆弱性和混淆语言的功能必须为补偿这些成本带来巨大的好处。 您认为此功能为证明其费用的语言带来的巨大好处是什么?

如果答案是“没有这样的好处”那么现在你知道为什么语言没有这个功能:因为它使语言变得更糟,网络。

如果有好处,我很乐意考虑其假设未来版本的语言的优点。

答案 2 :(得分:4)

你说,

  

按实例访问时,返回属性。静态访问时,返回类。

但是如果你在Keys内某处Material说什么呢?这是静态访问还是实例访问?这是指引用属性Keys还是嵌套类型Keys?它实际上是模棱两可的。

例如,

class Material
{
    class Keys
    {
        public static int Length;
    }

    string Keys { get; set; }

    public void Process()
    {
        // Does this refer to string.Length (via property Keys)
        // or Material.Keys.Length? It actually refers to both.
        Console.WriteLine(Keys.Length);
    }
}

正如评论中所指出的,这不是整个故事;但是几乎。拥有Color类型Color的属性并且没有冲突是有效的:

public Color Color { get; set; }

Color.FromName(...)   // refers to static method on the type ‘Color’
Color.ToString()      // refers to instance method on the property’s value

但这很容易解决,因为当前范围内的东西会赢得更多外部范围内的事物:

public class MyType { public string FromName(string name) { return null; } }
public MyType Color;

Color.FromName(...)   // unambiguously refers to MyType::FromName(string)
                      // via the property Color

在您的示例中不是那么容易 - 嵌套类Keys和属性Keys在同一范围内(具有相同的声明类型)。你如何决定优先考虑哪个?即使你决定给予其中一个优先权,这也只是略有用处,因为你仍然只能有两个同名的东西,一个必须是静态的而另一个是实例。

答案 3 :(得分:3)

与其他问题相比,我的回答从稍微不同的角度来处理问题。在C#语言规范中的以下两个语句中:

The same identifier may not be used in different definitions within one scope

The same identifier may not be used in different definitions within one scope, unless it is probably impossible for any ambiguity to arise when the identifier is used

,第一个更简单。

简单性是语言设计的关键目标,因为编译器和解释器作者更容易实现更简单的语言,生成和操作的工具更容易,初学者更容易学习,程序员更容易理解。在考虑任何语言特征时,该特征添加到语言中的复杂性应被视为否定,因此必须通过至少相等的有用性衡量来平衡。正如你所说,允许这样做不会增加真正的功能(因为它很容易解决),所以没有令人信服的理由通过包含它来进一步使C#规范复杂化。

答案 4 :(得分:2)

因为嵌套类KeysMaterial的成员,属性Keys也是如此。你有两个名为Keys的成员。

同样地,你不能有两个叫做同一个东西的属性:

public class Bar
{
    private bool Foo { get; set; }
    private string Foo { get; set; }
}

当您访问Foo您要访问哪一个时?

public class Material : Keys
{

    private Keys K { get; set; }
}

public class Keys
{

}

工作正常,但可能不是你想要的。