У меня есть перечисление в низкоуровневом пространстве имен. Я хотел бы предоставить класс или перечисление в пространстве имен среднего уровня, которое «наследует» перечисление низкого уровня.
namespace low
{
public enum base
{
x, y, z
}
}
namespace mid
{
public enum consume : low.base
{
}
}
Я надеюсь, что это возможно, или, возможно, какой-то класс, который может заменить потребление перечисления, который обеспечит уровень абстракции для перечисления, но все же позволит экземпляру этого класса получить доступ к перечислению.
Мысли?
РЕДАКТИРОВАТЬ: Одна из причин, по которой я не просто переключил это на conts в классах, заключается в том, что перечисление низкого уровня необходимо для службы, которую я должен потреблять. Мне дали WSDL и XSD, которые определяют структуру как перечисление. Услуга не может быть изменена.
Ответы:
Это невозможно. Перечисления не могут наследоваться от других перечислений. На самом деле все перечисления должны наследоваться от
System.Enum
. C # позволяет синтаксису изменять базовое представление значений перечисления, которое выглядит как наследование, но в действительности они все еще наследуются от System.enum.См. Раздел 8.5.2 спецификации CLI для полной информации. Соответствующая информация из спецификации
System.Enum
источник
switch
ситуации.Вы можете достичь того, что вы хотите с классами:
Теперь вы можете использовать эти классы аналогично тому, как они были перечислениями:
Обновление (после обновления вопроса):
Если вы присваиваете константы тем же значениям int, которые определены в существующем перечислении, вы можете привести между перечислением и константами, например:
источник
Enum.GetValues(typeof(MyEnum)
void Test() { foreach (System.Reflection.PropertyInfo pi in typeof(Consume).GetProperties()) { Console.WriteLine(pi.Name); } }
Краткий ответ: нет. Вы можете немного поиграть, если хотите:
Вы всегда можете сделать что-то вроде этого:
Но это не работает так здорово, потому что Base.A! = Consume.A
Вы всегда можете сделать что-то вроде этого, хотя:
Для того, чтобы перейти между Base и Consume ...
Вы также можете привести значения перечислений как целые и сравнивать их как целые, а не как перечисление, но это тоже отстой.
Возвращаемым методом расширения должен быть тип cast типа T.
источник
Base.A == (Base)Consume.A
int
было бы намного больше смысла. Когда перечисление будет иметь дробную часть!?!?!В приведенных выше решениях с использованием классов с константами int отсутствует безопасность типов. Т.е. вы можете изобрести новые значения, которые на самом деле не определены в классе. Кроме того, невозможно, например, написать метод, принимающий один из этих классов в качестве входных данных.
Вам нужно будет написать
Тем не менее, существует классическое решение старых времен Java, когда не было доступных перечислений. Это обеспечивает почти подобное перечислению поведение. Единственное предостережение в том, что эти константы не могут быть использованы внутри оператора switch.
источник
object
, делало бы значения разными для каждого экземпляра сборки, поэтому их нельзя сериализовать.Игнорируя тот факт, что база является зарезервированным словом, вы не можете делать наследование enum.
Лучшее, что вы можете сделать, это что-то вроде этого:
Поскольку все они имеют один и тот же базовый тип (то есть: int), вы можете присвоить значение из экземпляра одного типа другому, который был приведен. Не идеально, но это работает.
источник
Я знаю, что этот ответ немного запоздал, но вот что я в итоге сделал:
Тогда я могу делать такие вещи, как:
источник
Это то, что я сделал. То, что я сделал по-другому, это используйте одно и то же имя и
new
ключевое слово для «потребления»enum
. Поскольку имяenum
одно и то же, вы можете просто бездумно использовать его, и оно будет правильным. Плюс вы получаете intellisense. При настройке нужно просто позаботиться о том, чтобы значения копировались из базы, и синхронизировать их. Вы можете помочь этому наряду с комментариями кода. Это еще одна причина, почему в базе данных при храненииenum
значений я всегда сохраняю строку, а не значение. Потому что, если вы используете автоматически назначаемые увеличивающиеся целочисленные значения, они могут меняться со временем.источник
SmallMedium = 100,
), чтобы вы могли сохранять совместимость со старыми версиями вашего программного обеспечения при добавлении новых значений в базовый класс. Например, добавлениеHuge
размера в базовое перечисление присваивает4
его значению, но4
уже занятоSmallMedium
в производном классе.Huge
в базовый класс потребовало быHuge
в подклассе раньшеSmallMedium
BaseBall
может быть, не самое умное имя здесь. Это сбивает с толку. Поскольку бейсбол на самом деле вещь. Если вы пропустите, что это просто базовый класс для мяча, это выглядит очень странно, что волейбол наследует от физически меньшего бейсбола :). Мое предложение просто использоватьBall
Альтернативное решение
В моей компании мы избегаем «перепрыгивать через проекты», чтобы попасть в необычные проекты нижнего уровня. Например, наш уровень представления / API может ссылаться только на наш уровень домена, а уровень домена может ссылаться только на уровень данных.
Однако это проблема, когда есть перечисления, на которые должны ссылаться как уровни представления, так и уровни домена.
Вот решение, которое мы реализовали (пока). Это довольно хорошее решение и хорошо работает для нас. Другие ответы били все вокруг.
Основная предпосылка состоит в том, что перечисления не могут быть унаследованы - но классы могут. Так...
Затем "наследовать" перечисления в другом проекте более высокого уровня ...
Это имеет три реальных преимущества ...
Чтобы ссылаться на перечисления в первом проекте , вы можете использовать префикс класса: BaseEnums.StatusType.Pending или добавить «using static BaseEnums;» Заявление о вашем использовании.
Во втором проекте при работе с унаследованным классом, однако, я не мог заставить работать подход «используя статический ...» , поэтому все ссылки на «унаследованные перечисления» должны иметь префикс с классом, например, SubEnums.StatusType.Pending. , Если кто-нибудь придумает, как использовать «статический» подход во втором проекте, дайте мне знать.
Я уверен, что это можно изменить, чтобы сделать его еще лучше - но на самом деле это работает, и я использовал этот подход в рабочих проектах.
Пожалуйста, проголосуйте, если вы найдете это полезным.
источник
Я также хотел перегрузить Enums и создал комбинацию ответа «Семь» на этой странице и ответа «Мерлин Морган-Грэм» в дублирующем посте , а также пару улучшений.
Основные преимущества моего решения перед другими:
Это готовое решение, которое может быть вставлено непосредственно в ваш проект. Он разработан для моих нужд, поэтому, если вам не нравятся некоторые его части, просто замените их собственным кодом.
Во-первых, существует базовый класс
CEnum
, от которого должны наследоваться все пользовательские перечисления. Он имеет базовую функциональность, аналогичнуюEnum
типу .net :Во-вторых, здесь есть 2 производных класса Enum. Все производные классы нуждаются в некоторых основных методах, чтобы работать как положено. Это всегда один и тот же стандартный код; Я еще не нашел способ передать его в базовый класс. Код первого уровня наследования незначительно отличается от всех последующих уровней.
Классы были успешно протестированы с помощью следующего кода:
источник
Перечисления не являются реальными классами, даже если они выглядят так. Внутренне они обрабатываются так же, как и их базовый тип (по умолчанию Int32). Следовательно, вы можете сделать это только путем «копирования» отдельных значений из одного перечисления в другое и приведения их к их целому числу, чтобы сравнить их на равенство.
источник
Перечисления не могут быть получены из других перечислений, но только из int, uint, short, ushort, long, ulong, byte и sbyte.
Как сказал Паскаль, вы можете использовать другие значения или константы enum для инициализации значения enum, но это все.
источник
другое возможное решение:
НТН
источник
Это невозможно (как уже упоминалось @JaredPar). Попытка обойти эту логику - плохая практика. Если у вас есть, у
base class
которого естьenum
, вы должны перечислить все возможныеenum-values
варианты, и реализация класса должна работать со значениями, которые он знает.Например, предположим, что у вас есть базовый класс
BaseCatalog
, и у него естьenum ProductFormats
(Digital
,Physical
). Тогда вы можете иметьMusicCatalog
илиBookCatalog
то, что может содержать обаDigital
иPhysical
продукты, но если классClothingCatalog
, он должен содержать толькоPhysical
продукты.источник
Я понимаю, что немного опоздал на эту вечеринку, но вот мои два цента.
Нам всем ясно, что наследование Enum не поддерживается платформой. В этой теме были предложены некоторые очень интересные обходные пути, но ни один из них не был похож на то, что я искал, поэтому я сам попробовал.
Представляем: ObjectEnum
Вы можете проверить код и документацию здесь: https://github.com/dimi3tron/ObjectEnum .
И пакет здесь: https://www.nuget.org/packages/ObjectEnum
Или просто установите его:
Install-Package ObjectEnum
Короче говоря,
ObjectEnum<TEnum>
действует как обертка для любого перечисления. Переопределив GetDefinedValues () в подклассах, можно указать, какие значения перечисления действительны для этого конкретного класса.Был добавлен ряд перегрузок операторов, чтобы заставить
ObjectEnum<TEnum>
экземпляр вести себя так, как если бы он был экземпляром базового перечисления, с учетом ограничений на определенные значения. Это означает, что вы можете легко сравнить экземпляр со значением типа int или enum и, таким образом, использовать его в случае переключателя или в любом другом условном выражении.Я хотел бы обратиться к упомянутому выше репозиторию github за примерами и дополнительной информацией.
Я надеюсь, что вы найдете это полезным. Не стесняйтесь комментировать или открыть вопрос на GitHub для дальнейших мыслей или комментариев.
Вот несколько коротких примеров того, что вы можете сделать с
ObjectEnum<TEnum>
:источник
Вы можете выполнять наследование в enum, однако оно ограничено только следующими типами. int, uint, byte, sbyte, short, ushort, long, ulong
Например
источник