枚举的范围是多少?

时间:2010-05-06 04:38:25

标签: c# enums

在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

,预期输出为:Book 5是TextBook

9 个答案:

答案 0 :(得分:11)

正如其他人所说,不可能。如果它们是标志,则可以组合枚举值:

[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
}

答案 1 :(得分:8)

根据C#标准(p612,C#编程语言),枚举的值必须是一个常量整数(或任何类似的类型 - 长,字节,字节,短等),因此一系列值不是没有效。

我的编译器(VS2008)同意规范。

由于你不能在枚举中重复名称,所以你得到的最接近的是:

public enum BookType
{
    Novel = 1,
    Journal = 2,
    Reference = 3,
    TextBook4 = 4,
    TextBook5 = 5, ...
    TextBook10 = 10
}

实际上这很难看。也许枚举不能解决你的特定问题......

答案 2 :(得分:4)

由于您无法为枚举指定值范围,我想到了另一种方法,以便将枚举指定为限制值(示例基于时间):

    private enum eTiming
    {
        eOnTime = 0,
        eSlightDelay = 5,
        eMinorDelay = 15,
        eDelayed = 30,
        eMajorDelay = 45,
        eSevereDelay = 60
    }

    private static eTiming CheckIfTimeDelayed(TimeSpan tsTime)
    {
        eTiming etiming = eTiming.eOnTime;

        foreach (eTiming eT in Enum.GetValues(typeof(eTiming)))
        {
            if (Convert.ToInt16(eT) <= tsTime.TotalMinutes)
                etiming = eT;
        }

        return etiming;
    }

这假设enum已排序,并且使用带符号( - )值意外地工作。

答案 3 :(得分:3)

有点偏离,您可以使用具有只读字段的普通类来模拟枚举。

e.g。类似的东西会解决你的问题:

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");
    }
}

它比普通的枚举更冗长,但它确实允许你以类似枚举的方式定义远程成员。

e.g。

 var bookType = (BookType)5;
 Console.WriteLine(bookType);

答案 4 :(得分:2)

如果您可以自己将值分配给枚举字符串,那么您可以使用一些bitmagic将多个int值映射到相同的枚举值。子类型可以为每个BookType(NovelTypes,JournalTypes等)自己枚举。

缺点

  • 在投射到BookType
  • 时确实需要修改一些值
  • 每个子类型范围都相同(当前示例中为16。
  • 它比简单的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等。

答案 5 :(得分:1)

不,不是。如果您尝试映射的数字常量确实具有相同的含义,则每个数字常量仍需要一个单独的成员。像TextBook4,TextBook5等

答案 6 :(得分:1)

您可以选择字典。

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]

编辑:如果字典属于班级,您也可以只读字典。

您可以使用枚举作为字典值而不是字符串。

答案 7 :(得分:0)

也许你想问一个相关的问题,那就是:你能不能有一个以上的枚举(不确定我的术语是否正确,但我的例子会说明我的意思)?

在C#中,可以执行以下操作:

public enum BookType
{
    Novel = 1,
    Journal = 2,
    Magazine = 2,
    Reference = 3,
    TextBook = 4,
    LabWorkbook = 4,
    Dictionary = 5,
    Encyclopedia = 5
}

这样,您可以在代码中使用BookType.JournalBookType.Magazine,其中任何一个都与值2同义。这个是否应该完成是另一回事 - 我不熟悉支持或反对的论据(我想说“如果C#允许它,它必须是正常的”,但那会完全疯了)。

答案 8 :(得分:0)

对你的问题最简单的答案是否。实现你想要的最简单的方法是:

public enum BookType
{
    Novel = 1,
    Journal = 2,
    Reference = 3,
    TextBook = 4
}

public void bookOutput(int book)
{
   if(book < 4)
       Console.Writeline("Book "+book+" is a " + ((BookType)book).ToString());
   else
       Console.Writeline("Book "+book+" is a " + BookType.TextBook.ToString());
}

我们的想法是让enum成为单独的值,并使用逻辑语句处理范围。