В C#, может Вы использовать диапазоны числа в перечислимых типах, например
public enum BookType
{
Novel = 1,
Journal = 2,
Reference = 3,
TextBook = 4 .. 10
}
Править: Причина это необходимо, состоит в том, чтобы бросить от числа до перечислимого типа, например:
int iBook = 5
BookType btBook = (BookType)ibook
Debug.Print "Book " + ibook + " is a " btBook
и ожидаемый вывод: Книгой 5 является TextBook
Согласно стандарту C # (p612, язык программирования C #) значение, передаваемое перечислению, должно быть постоянным целым числом (или любым подобным типом - длинным, байтовым, sbyte, коротким и т. Д.), Поэтому диапазон значений не не действует.
Мой компилятор (VS2008) согласен со спецификацией.
Поскольку вы не можете повторять имена в перечислении, самое близкое, что вы получите, будет примерно таким:
public enum BookType
{
Novel = 1,
Journal = 2,
Reference = 3,
TextBook4 = 4,
TextBook5 = 5, ...
TextBook10 = 10
}
Что на самом деле довольно некрасиво. Возможно, перечисление не является решением вашей конкретной проблемы ...
Немного оффтопика, вы можете имитировать перечисления, используя обычные классы с полями только для чтения.
например, что-то похожее на это решит вашу проблему:
public sealed class BookType
{
public static readonly BookType Novel = new BookType(1, 1, "Novel");
public static readonly BookType Journal = new BookType(2, 2, "Journal");
public static readonly BookType Reference = new BookType(3, 3, "Reference");
public static readonly BookType Textbook = new BookType(4, 10, "Textbook");
public int Low { get; private set; }
public int High { get; private set; }
private string name;
private static class BookTypeLookup
{
public static readonly Dictionary<int, BookType> lookup = new Dictionary<int, BookType>();
}
private BookType(int low, int high, string name)
{
this.Low = low;
this.High = high;
this.name = name;
for (int i = low; i <= high; i++)
BookTypeLookup.lookup.Add(i, this);
}
public override string ToString()
{
return name;
}
public static implicit operator BookType(int value)
{
BookType result = null;
if (BookTypeLookup.lookup.TryGetValue(value, out result))
return result;
throw new ArgumentOutOfRangeException("BookType not found");
}
}
Это немного более многословный вариант, чем обычное перечисление, но он позволяет вам определять ранжируемые члены подобно перечислению.
например,
var bookType = (BookType)5;
Console.WriteLine(bookType);
Вы можете выбрать словарь.
var BookType = new Dictionary<int, string>();
BookType.Add(1, "Novel");
BookType.Add(2, "Journal");
BookType.Add(3, "Reference");
BookType.Add(4, "TextBook");
BookType.Add(5, "TextBook");
BookType.Add(6, "TextBook");
BookType.Add(7, "TextBook");
BookType.Add(8, "TextBook");
BookType.Add(9, "TextBook");
BookType.Add(10, "TextBook");
int iBook = 5
Debug.Print "Book " + iBook + " is a " BookType[iBook]
Редактировать: Вы также можете объявить свой словарь доступным для чтения, если он находится на уровне класса.
Вы можете использовать перечисление в качестве значения словаря вместо строки.
Возможно, вы хотели задать смежный вопрос: можно ли иметь более одного перечисления (не уверен, что правильно использую терминологию, но мой пример покажет, что я имею в виду) для каждого значения?
В C# вы можете сделать что-то вроде этого:
public enum BookType
{
Novel = 1,
Journal = 2,
Magazine = 2,
Reference = 3,
TextBook = 4,
LabWorkbook = 4,
Dictionary = 5,
Encyclopedia = 5
}
Таким образом, вы можете использовать в коде либо BookType.Journal
, либо BookType.Magazine
, любой из которых является синонимом значения 2
. Следует ли это делать - это другой вопрос - я не знаком с аргументами за или против этого (я хотел бы сказать "если C# это позволяет, то это должно быть нормально", но это было бы полным безумием).
Если вы можете сами присваивать значения enum-строкам, тогда вы можете использовать некоторую битовую магию для сопоставления нескольких значений int одному значению enum. Подтипы могут быть сами перечислениями для каждого BookType
(NovelTypes, JournalTypes, etc).
С другой стороны
BookType
Novel = 3
. Пример кода:
class Program
{
/// <summary> Number of subtypes reserved for each BookType. </summary>
private const byte BookTypeStep = 16;
/// <summary> Bitmask to use to extract BookType from a byte. </summary>
private const byte BookTypeExtractor = Byte.MaxValue - BookTypeStep + 1;
/// <summary> Bitmask to use to extract Book subtype from a byte. </summary>
private const byte BookSubTypeExtractor = BookTypeStep -1;
public enum BookType : byte
{
Unknown = 0,
Novel = BookTypeStep * 1,
Journal = BookTypeStep * 2,
Reference = BookTypeStep * 3,
TextBook = BookTypeStep * 4,
}
static void Main(string[] args)
{
for(int i = 16; i < 80; i++)
{
Console.WriteLine("{0}\tof type {1} ({2}),\tsubtype nr {3}",
i,
i & BookTypeExtractor,
(BookType)(i & BookTypeExtractor),
i & BookSubTypeExtractor
);
}
Console.ReadLine();
}
}
В данном примере диапазоны 16-31 для романов, 32-47 для журналов и т.д.
Как сказали другие, нет, это невозможно. Можно комбинировать значения перечислений, если они являются флагами:
[Flags]
public enum BookType
{
Novel = 0,
Journal = 1 << 0,
Reference = 1 << 1,
TextBook1 = 1 << 2,
TextBook2 = 1 << 3,
TextBook3 = 1 << 4,
TextBook4 = 1 << 5,
TextBook5 = 1 << 6,
TextBooks1To5 = TextBook1 | TextBook2 | TextBook3 | TextBook4 | TextBook5
}
Нет, это не так. Если числовые константы, которые вы пытаетесь сопоставить, действительно имеют одинаковое значение, вам все равно потребуется отдельный член для каждой числовой константы. Например, TextBook4, TextBook5 и т. Д.