Почему имя члена класса не может совпадать с одним из его вложенных классов?
Или почему невозможно сделать следующее:
class Material
{
class Keys
{
...
}
Material.Keys Keys { get; set; } // Illegal
}
Я не вижу никакой возможной двусмысленности. При обращении к экземпляру возвращайте свойство. При доступе статически возвращайте класс. Или я что-то упускаю?
Я не прошу "исправить" (я знаю, что могу просто назвать его по-другому, например MaterialKeys или тому подобное), но больше технической причины этого предела.
Ответы
Ответ 1
Но представьте себе, что вы это сделали:
class Material
{
class Keys
{
...
}
static Material.Keys Keys = new Keys();
}
Теперь оба находятся в "статическом" объеме. Теперь, может ли компилятор устранить неоднозначность во всех случаях? Если нет, то это невозможно.
Я полагаю, что возможно, что неоднозначность будет работать для статических полей/свойств/методов, а не для членов. Или наоборот. Если бы это было так, вы хотите, чтобы спецификация языка позволяла члену экземпляра иметь то же имя, что и внутренний класс, но запретить его для статики? Это просто сбивает с толку.
Но тогда, когда член совпадает с именем внутреннего класса, все равно запутывается.
Ответ 2
"Все, что не является двусмысленным, должно быть законным", абсолютно НЕ является конструктивным принципом языка С#. Язык С# разработан как язык "ямы качества" ; то есть правила языка должны бросать вас в яму, полную явно правильного кода, и вам нужно работать, чтобы выбраться из ямы, чтобы превратить ее в неправильный код. Идея о том, что "все, что не является двусмысленным, должно быть законным", работает в большинстве случаев непосредственно против концепции языка "ямы качества" .
Кроме того, ваша идея о том, что мне нужно предоставить вам обоснование несоблюдения функции, - назад. Нам не нужно давать оправдание тому, чтобы не выполнять функцию. Скорее, предлагаемые функции должны быть оправданы, демонстрируя, что их преимущества перевешивают их огромные издержки. Особенности очень дороги, и у нас ограниченный бюджет; мы должны делать только самые лучшие функции, чтобы приносить свои преимущества нашим клиентам.
Предлагаемая функция позволяет легко производить код, который является хрупким и запутанным; это помогает сделать С# в "яму отчаяния" вместо языка "ямы качества" . Особенности, которые добавляют хрупкость и путаницу к языку, должны принести огромную пользу, чтобы компенсировать эти затраты. На ваш взгляд, огромная выгода, которую эта функция добавляет к языку, оправдывающему его издержки?
Если ответ "нет такой выгоды", то теперь вы знаете, почему язык не имеет этой функции: потому что это делает язык хуже, net.
Если есть преимущество, я рад рассмотреть его достоинства для гипотетических будущих версий языка.
Ответ 3
Ты сказал,
При обращении к экземпляру возвращает свойство. При доступе статически возвращайте класс.
Но что, если вы скажете только 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
находятся в одной области (имеют один и тот же тип объявления). Как вы решаете, какой приоритет? И даже если вы решили перенести один из них на приоритет, это будет лишь незначительно полезным, потому что у вас могут быть только две вещи с одним и тем же именем, и один из них должен быть статическим, а другой -.
Ответ 4
Мой ответ подходит к вопросу с несколько иной точки зрения по сравнению с другими вопросами. Из следующих двух утверждений в спецификации языка С#:
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
первое намного проще.
Простота - ключевая цель в дизайне языка, потому что проще для разработчиков компилятора и интерпретатора проще упростить, упростить инструменты для генерации и манипулирования, проще для начинающих учиться и проще для программистов понять. При рассмотрении любой языковой функции сложность, которую эта функция добавляет к языку, должна рассматриваться как отрицательная и поэтому должна быть сбалансирована по меньшей мере равной мере полезности. Как вы заявили, что это не добавит никакой реальной функциональности (поскольку так легко работать), поэтому не было никаких веских оснований для дальнейшего усложнения спецификации С#, включая ее.
Ответ 5
Поскольку вложенный класс 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
{
}
Работает нормально, но, вероятно, не то, что вам нужно.