或者为什么以下不可能:
class Material
{
class Keys
{
...
}
Material.Keys Keys { get; set; } // Illegal
}
我没有看到任何可能的歧义。按实例访问时,返回属性。静态访问时,返回类。或者我错过了什么?
我不是要求“修复”(我知道我可以用不同的名称命名,比如MaterialKeys之类的东西),但更多的是这个限制背后的技术原因。
答案 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)
因为嵌套类Keys
是Material
的成员,属性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
{
}
工作正常,但可能不是你想要的。