19

或者为什么以下不可能:

class Material
{
    class Keys
    {
        ...
    }

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

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

我不是要求“修复”(我知道我可以将其命名为不同的名称,例如 MaterialKeys 等),但更多的是此限制背后的技术原因。

4

5 回答 5

17

但是想象一下你有这个:

class Material
{
    class Keys
    {
        ...
    }

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

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

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

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

于 2011-01-19T03:16:02.550 回答
15

“任何不模棱两可的东西都应该是合法的”绝对不是 C# 语言的设计原则。C#语言被设计成一个“质量坑”的语言;也就是说,语言的规则应该把你扔进一个充满明显正确代码的坑里,你必须努力爬出这个坑才能把它变成不正确的代码。在大多数情况下,“任何不模糊的东西都应该是合法的”的想法直接违背了“质量坑”语言的概念。

此外,您认为我需要为您提供不做某项功能的理由的想法是倒退的。我们不需要为不做某项功能提供理由。相反,提议的功能必须通过证明其收益超过其巨大成本来证明其合理性。功能非常昂贵,我们的预算有限;我们必须只做最好的功能,才能为我们的客户带来好处。

您提出的功能可以轻松生成易碎且令人困惑的代码;它有助于使 C# 成为“绝望之坑”语言,而不是“质量之坑”语言。给语言增加脆弱性和混乱的特性必须增加巨大的好处来补偿这些成本。在你看来,这个特性给语言带来的巨大好处是什么,证明它的成本是合理的?

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

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

于 2011-01-19T07:11:27.307 回答
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在同一范围内(具有相同的声明类型)。你如何决定优先考虑哪个?即使你决定给其中一个优先级,这也只会有一点用处,因为你仍然只能有两个同名的东西,一个必须是静态的,另一个必须是实例。

于 2011-01-19T02:52:34.927 回答
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# 规范。

于 2011-01-19T04:27:15.927 回答
2

因为嵌套类是属性Keys的成员。你有两个成员叫。MaterialKeysKeys

以同样的方式,您不能将两个属性称为同一事物:

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
{

}

工作正常,但可能不是你所追求的。

于 2011-01-19T02:49:10.867 回答