Хобрук: Ваш путь к мастерству в программировании

Создать переопределяемое перечисление в родительском классе

Я хочу создать вложенную структуру, в которой каждый класс представляет страну, наследуя один и тот же родительский класс Country. Каждый дочерний класс должен иметь перечисление, представляющее различные состояния States.

Цель состоит в том, чтобы выбрать страну, а затем один из ее штатов.

Контент будет сохранен в словаре Dictionary<Tuple<string, Type>, object>, где Types будут Country и Country.States.

Я попытался реализовать _7 _ / _ 8_ с enum с именем States, но это не сработало, так как это определение типа.

Есть ли обходной путь?

public abstract class Country
{
    public abstract enum States { get; }
}

public class CountryA : Country
{
    public new enum States
    {
        StateA,
        StateB,
        StateC,
    }
}
03.04.2018

  • Я люблю запах X Y по утрам. серьезно, хотя ты не можешь. Лучшее, на что вы могли надеяться, - это доступ к различным уровням перечислений через int или какое-то отражение с какой-то реализацией adhock. 03.04.2018
  • Использование перечислений для хранения состояний страны звучит ужасно. 03.04.2018
  • @crazyGamer Использование классов для представления стран еще хуже. ОП: у вас действительно будет более 200 классов с тысячами перечислений? Будете ли вы перестраивать свое приложение каждый раз при смене страны? А их состояния? 03.04.2018
  • Интересно, могут ли public class Country { public string CountryName;} и public class State : Country { public string StateName; } подойти лучше. Но мне это не нравится. В любом случае, наличие нескольких классов для каждой страны звучит сложно. 03.04.2018
  • ребята, это просто университетский проект. Я просто хочу сохранить несколько примеров: D (кстати, проект о плагинах) 03.04.2018

Ответы:


1

Ваш дизайн ошибочен, вам нужно создать единственный класс Country со свойством, например. public string[] States { get; set; }.

Затем создайте экземпляры (объекты) вашего Country класса, в каждом из которых States установлены необходимые элементы:

var usa    = new Country { Name = "USA",    States = new[] { "Alabama", ... } };
var canada = new Country { Name = "Canada", States = new[] { ... } };
// etc
03.04.2018
  • Эти экземпляры могут быть статическими общедоступными членами самого класса, а затем это почти как перечисление. 03.04.2018
  • Вместо string[] я бы предложил HashSet<string> 03.04.2018

  • 2

    У вас есть несколько вариантов:

    Вы можете создать перечисление во время выполнения (см. Здесь: Динамически создавать перечисление), но я не Не думаю, что это будет соответствовать вашим потребностям, поскольку я предполагаю, что вы идете по маршруту enum для простоты использования в кодировании, чем что-либо еще.

    Вы можете реализовать шаблон typeafe enum (см. Здесь: typesafe enum pattern), но это еще больше кода просто для возможности использовать дизайн, имитирующий перечисления, при кодировании остальной логики.

    Мой совет - использовать словарь и создавать свои «состояния» при создании экземпляра из файла настроек или внешнего источника данных. В конце концов, названия стран и их штатов / городов и т. Д. Время от времени меняются. Запирание себя в жестко закодированной ситуации, к которой вы стремитесь, не поддержит такие будущие изменения.

    Удачи!

    [Отредактировано после ответа camilo-terevinto]

    03.04.2018
  • Невозможно сделать то, что вы хотите сделать. Пожалуйста, покажите, насколько это правда. Конечно, это возможно, это займет очень много времени, и оно того не стоит. 03.04.2018
  • @CamiloTerevinto, конечно, есть шаблон typeafe enum, которым можно злоупотреблять, чтобы удовлетворить потребности OP. Я забыл об этом. 03.04.2018

  • 3

    Хотя я, конечно, согласен с тем, что ваш дизайн, скорее всего, ошибочен, поскольку вам потребуются сотни классов и перечислений, я полностью не согласен с другими ответами, что «это невозможно».

    Конечно, можно использовать дженерики (, помня, что вы не можете полностью ограничить Enums ):

    public abstract class Country<TStates> 
        where TStates: struct, IConvertible, IFormattable, IComparable
    {
        public abstract TStates[] States { get; }
    }
    
    public enum UnitedStatesStates
    {
        WhoCares, WhoCares2
    }
    
    public class UnitedStatesCountry : Country<UnitedStatesStates>
    {
        public override UnitedStatesStates[] States { get; }
    }
    

    Я очень сомневаюсь, что это будет полезно в (не очень долгой) перспективе.

    03.04.2018
  • Вы можете еще больше ограничить его с помощью некоторого IL, однако я не уверен, что его варианты использования соответствуют реализации дженериков. В любом случае, я дам вам положительный голос, так как сегодня вечером трудно заработать очки 03.04.2018

  • 4

    Вы просите сделать enum наследуемым, это возможно, если вы используете не enum, а класс с static public членами (которые могут быть унаследованы и иметь разные наборы членов для каждого типа). Он ведет себя почти как перечисление:

    public class Country1
    {
        public static State State1 { get; } = new State("State 1");
        public static State State2 { get; } = new State("State 2");
        ...
    }
    

    Должно быть понятно, что такое Country1.State1, верно? State может быть более сложным объектом, чем просто string. Как видите, наследование не требуется, потому что страна определяет состояния как разные члены.

    Вы можете следовать тому же принципу, чтобы реализовать длинную цепочку объектов: Planet.Continent.Country.State.Province.Town.Street.Hause ..


    Ты говоришь

    Контент будет сохранен в словаре Dictionary<Tuple<string, Type>, object>, где типы будут Country и Country.States.

    Не надо. Это разные типы, это плохой выбор ключа. Если вам нужно перечислить (найти) состояния, просто добавьте еще один член в Country:

    public static IEnumerable<State> States
    {
        get
        {
            yield return State1;
            yield return State2;
            ...
        }
    }
    

    Тогда поиск чего-либо может быть простым linq:

    var stateAInCountry1 = ...Countries.OfType<Contry1>().Single().States.Single(o => o.Name == "A");
    var countriesWithStateA = ...Countries.Where(o => o.States.Any(o => o.Name == "A"));
    

    Не уверен, какую проблему вы решаете, вводя словарь, но вы можете инициализировать дополнительную структуру данных с помощью правильного ключа, если вы предоставили способ простой итерации.

    03.04.2018

    5

    Мне не так ясно, хотите ли вы чего-то еще, кроме того, что компилятор напомнил вам об определении этих различных (!) Перечислений.

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

    Что вы могли сделать, так это объявить его как

    public abstract string[] States {get;}
    

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

    03.04.2018
    Новые материалы

    ВЫ РЕГРЕСС ЭТО?
    Чтобы понять, когда использовать регрессионный анализ, мы должны сначала понять, что именно он делает. Вот простой ответ, который появляется, когда вы используете Google: Регрессионный..

    Не зря же это называют интеллектом
    Стек — C#, Oracle Опыт — 4 года Работа — Разведывательный корпус Мне пора служить Может быть, я немного приукрашиваю себя, но там, где я живу, есть обязательная военная служба на 3..

    LeetCode Проблема 41. Первый пропущенный положительный результат
    LeetCode Проблема 41. Первый пропущенный положительный результат Учитывая несортированный массив целых чисел, найдите наименьшее пропущенное положительное целое число. Пример 1: Input:..

    Расистский и сексистский робот, обученный в Интернете
    Его ИИ основан на предвзятых данных, которые создают предрассудки. Он словно переходит из одного эпизода в другой из серии Черное зеркало , а вместо этого представляет собой хронику..

    Управление состоянием в микрофронтендах
    Стратегии бесперебойного сотрудничества Микро-фронтенды — это быстро растущая тенденция в сфере фронтенда, гарантирующая, что удовольствие не ограничивается исключительно бэкэнд-системами..

    Декларативное и функциональное программирование в стиле LINQ с использованием JavaScript с использованием каррирования и генератора ...
    LINQ - одна из лучших функций C #, которая обеспечивает элегантный способ написания кода декларативного и функционального стиля, который легко читать и понимать. Благодаря таким функциям ES6,..

    Структуры данных в C ++ - Часть 1
    Реализация общих структур данных в C ++ C ++ - это расширение языка программирования C, которое поддерживает создание классов, поэтому оно известно как C с классами . Он используется для..