Вложенные конфликты имен перечисления и свойства

Существуют некоторые связанные вопросы здесь и здесь, но они действительно не дали мне удовлетворительные ответы. Проблема состоит в том, что перечисления, вложенные в классе в C#, не могут иметь того же имени как свойство класса. Мой пример:

public class Card
{
    public enum Suit
    {
        Clubs,
        Diamonds,
        Spades,
        Hearts
    }

    public enum Rank
    {
        Two,
        Three,
        ...
        King,
        Ace
    }

    public Suit Suit { get; private set; }
    public Rank Rank { get; private set; }
    ...
}

Существует несколько опций бездельничать это, но они не кажутся правильным мне.

Я мог переместить перечисления вне класса, но затем Вы просто скажете Suit вместо Card.Suit, который кажется неправильным мне. Что такое a Suit вне контекста a Card?

Я мог переместить их вне класса и изменить их на что-то как CardSuit и CardRank, но затем я чувствовал бы, что пеку контекстную информацию на название перечисления, когда это должно быть обработано именем пространства имен или классом.

Я мог изменить имена перечислений к Suits и Ranks, но это нарушает рекомендации по именованию Microsoft. И это просто не чувствует себя хорошо.

Я мог изменить имена свойства. Но к какой? Это интуитивно чувствует себя хорошо мне, чтобы хотеть сказать Suit = Card.Suit.Spades.

Я мог переместить перечисления в отдельный статический названный класс CardInfo содержа только эти перечисления. Если я не могу придумать ничто больше, я думаю, что это - наилучший вариант.

Таким образом, я задаюсь вопросом, что другие люди сделали в аналогичных ситуациях. Также было бы хорошо знать, почему это запрещено. Возможно, Eric Lippert или кто-то могли вмешаться на решении запретить его? На него кажется, что только создает неоднозначность в классе, и это могло быть разрешено путем принуждения использования this.Suit для имени свойства. (Подобный устранению неоднозначности между местными жителями и участниками.) Я предполагаю, что это было не учтено из-за "каждой функции, запускает с-100 точек" вещь, но мне было бы любопытно на предмет дискуссий по поводу этого.

29
задан Community 23 May 2017 в 12:09
поделиться

5 ответов

Также было бы неплохо узнать, почему это запрещено. Может быть, Эрик Липперт или кто-то может вмешаться в решение запретить это?

Суть правила состоит в том, чтобы гарантировать отсутствие двусмысленности внутри класса при поиске имени. Определенные области кода обозначены как определяющие «пространство объявлений». Основное правило пространств объявлений : никакие две вещи, объявленные в одном пространстве объявлений, не имеют одинакового имени (за исключением методов, которые должны отличаться подписью , а не именем ].)

Исключения из этого правила только сбивают с толку, а не меньше. Я согласен с тем, что досадно, что у вас не может быть свойства и перечисления с тем же именем, объявленных в одном и том же пространстве объявлений, но как только вы начнете делать исключения, это просто станет беспорядком. Обычно приятным свойством является то, что имя однозначно идентифицирует группу методов, параметр типа, свойство и т. Д.

Обратите внимание, что это правило применяется к вещам , объявленным в пространстве объявлений, а не к вещам , используемым в пространстве объявлений. Совершенно законно сказать «public Suit Suit {get; set;}» при условии, что тип Suit не объявлен в том же пространстве декларации, что и свойство. Когда кто-то говорит «Suit.X», выяснить, относится ли X к типу (то есть X является статическим членом) или свойству (то есть X является членом экземпляра), немного сложно. Подробности см. В моей статье о том, как мы это делаем:

http://blogs.msdn.com/ericlippert/archive/2009/07/06/color-color.aspx

19
ответ дан 28 November 2019 в 02:03
поделиться

Я бы переместил перечисления за пределы определения класса и использовал пространство имен, чтобы указать, что они относятся к картам. Я вообще не люблю перечисления, вложенные в классы. Вы правы насчет множественности, хотя: единственное число для обычных перечислений, множественное - для перечислений флагов.

-121--1393988-

можно использовать функцию Thread.Sleep ()

Thread.sleep(4000);
myfunction();

Ваша функция будет выполняться через 4 секунды. Однако это может приостановить всю программу...

-121--2020330-

Перечисления в основном представляют собой определенные типы данных. Вы не будете использовать «int» или «string» в качестве имени члена, поэтому я думаю, что не менее плохая идея использовать имена перечисления и имена членов в вашем случае.

1
ответ дан 28 November 2019 в 02:03
поделиться

Я предпочитаю именовать перечисления с помощью существительного, за которым следуют Параметры. В вашем случае:

SuitOptions
RankOptions

Ведь перечисление - это всего лишь набор возможных вариантов, верно?

У вас тогда будет:

myCard.Suit = Card.SuitOptions.Clubs;

Что, на мой взгляд, имеет смысл и вы все еще можете знать при просмотре текста, является ли тогда перечислением или свойством.

-121--1393986-

Может быть:

case "$DIVIDER" in
(*\\*) DIVIDER=$(echo "$DIVIDER" | sed 's/\\/\\\\/g');;
esac

Я играл с этим сценарием:

for DIVIDER in 'xx\n' 'xxx\\ddd' "xxx"
do
    echo "In:  <<$DIVIDER>>"
    case "$DIVIDER" in     (*\\*) DIVIDER=$(echo "$DIVIDER" | sed 's/\\/\\\\/g');;
    esac
    echo "Out: <<$DIVIDER>>"
done

Run with 'ksh' или 'bash' (но не 'sh') на MacOS X:

In:  <<xx\n>>
Out: <<xx\\n>>
In:  <<xxx\\ddd>>
Out: <<xxx\\\\ddd>>
In:  <<xxx>>
Out: <<xxx>>
-121--4817541-

Я бы переместил перечисления за пределы определения класса и использовал пространство имен, чтобы указать, что они связаны Я вообще не люблю перечисления, вложенные в классы. Вы правы насчет множественности, хотя: единственное число для обычных перечислений, множественное - для перечислений флагов.

1
ответ дан 28 November 2019 в 02:03
поделиться

Я предпочитаю называть перечисления, используя существительное, за которым следует Параметры. В вашем случае:

SuitOptions
RankOptions

В конце концов, перечисление - это всего лишь набор возможных параметров, не так ли?

Тогда у вас будет:

myCard.Suit = Card.SuitOptions.Clubs;

Что, на мой взгляд, имеет смысл, и при просмотре текста вы все еще можете узнать, является ли это перечислением или свойством.

3
ответ дан 28 November 2019 в 02:03
поделиться

Я бы согласился переместить определение перечисления в отдельное место. В настоящее время перечисления видны только через карточку, поэтому, если вы хотите проверить туза, вам нужно будет сделать

if (card.CardSuit == Card.Suit.Ace) { }  //need different name for Suit field

Где, если вы переместили его в отдельное определение, вы могли бы сделать это, если сделаете его глобальным:

if (card.Suit == Suit.Ace) { } //no naming clashes, easier to read
3
ответ дан 28 November 2019 в 02:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: