枚举可以使用范围吗?

发布于 2024-08-31 15:52:00 字数 348 浏览 5 评论 0原文

在 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 is a TextBook

In C#, can you use number ranges in enum types, for example

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

EDIT: The reason this is needed is to cast from a number to the enum type, eg:

int iBook = 5
BookType btBook = (BookType)ibook
Debug.Print "Book " + ibook + " is a " btBook

and the expected output is: Book 5 is a TextBook

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

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

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

As others have said, no it isn't possible. It is possible to combine enum values if they are flags:

[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
}
浸婚纱 2024-09-07 15:52:00

根据 C# 标准(p612,C# 编程语言),赋予枚举的值必须是常量整数(或任何类似类型 - long、byte、sbyte、short 等),因此值范围无效。

我的编译器(VS2008)符合规范。

由于您不能在枚举中重复名称,因此您将得到的最接近的结果是这样的:

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

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

According to the C# standard (p612, The C# Programming Language) the value given to an enumeration must be a constant integer (or any similar type - long, byte, sbyte, short, etc), so a range of values isn't valid.

My compiler (VS2008) agrees with the spec.

Since you can't repeat names within an enumeration, the closest you'll get is something like this:

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

Which is actually pretty ugly. Perhaps an enum is not the solution to your particular problem ...

御弟哥哥 2024-09-07 15:52:00

由于您无法为枚举分配值范围,因此我想到了另一种方法来将枚举分配为限制值(该示例基于时间):

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

这是假设枚举已排序,并且意外地工作带符号 (-) 值。

Since you are unable to assign a value range to an enum, I thought of an alternative approach in order to assign an enum as a limit value (the example is based on time):

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

This is assuming that the enum is sorted, and works unexpectedly with signed (-) values.

醉梦枕江山 2024-09-07 15:52:00

有点题外话,您可以使用带有只读字段的普通类来模拟枚举。

例如,与此类似的东西可以解决您的问题:

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

Somewhat offtopic, you can simulate enums using normal classes with readonly fields.

e.g. something similair to this would solve your problem:

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

It's quite a bit more verbose than a normal enum, but it does allow you to define ranged members in an enum like manner.

e.g.

 var bookType = (BookType)5;
 Console.WriteLine(bookType);
給妳壹絲溫柔 2024-09-07 15:52:00

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

缺点是,

  • 在转换为 BookType 时,它确实需要进行一些值修改,
  • 每个子类型范围的大小相同(当前示例中为 16)。
  • 它的可读性比简单的 Novel = 3 稍差一些。 code> 类型的映射。

示例代码:

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 等。

If you can assign the values to enum-strings yourself then you can use some bitmagic to map multiple int values to same enum value. Subtypes could be enums themselves for every BookType (NovelTypes, JournalTypes, etc).

On the downside

  • it does require some value modification when casting to BookType
  • every subtype range is of the same size (16 in current example.
  • it is a bit less readable than simple Novel = 3 kind of mapping.

Example code:

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

This example has ranges 16-31 for Novels, 32-47 for journals, etc.

忘年祭陌 2024-09-07 15:52:00

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

No, it's not. If the numeric constants you're trying to map to truly have the same meaning, you would still need a separate member for each numeric constant. Like TextBook4, TextBook5, etc.

时光磨忆 2024-09-07 15:52:00

您可以选择字典。

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]

编辑:如果字典处于类级别,您还可以将其声明为只读。

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

You can opt for a dictionary rather.

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]

Edit: You can also declare your dictionary readonly if it's in class level.

You can use an enum as the Dictionary value instead of string.

七度光 2024-09-07 15:52:00

也许您想问一个相关的问题,即:对于每个值,您可以有多个枚举(不确定我的术语是否正确,但我的示例将显示我的意思)?

在 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# 允许,它一定没问题”,但这会彻底疯狂)。

Perhaps you meant to ask a related question, which is: can you have more than one enumeration (not sure I have the terminology correct, but my example will show what I mean) for each value?

In C#, you can do something like this:

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

This way, you can use either BookType.Journal or BookType.Magazine in your code, either of which is synonymous with the value 2. Whether this should be done is another matter - I'm not familiar with the arguments for or against this (I'd like to say "if C# allows it, it must be OK", but that would be utterly crazy).

明媚殇 2024-09-07 15:52:00

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

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

这个想法是让枚举成为单独的值并用逻辑语句处理范围。

The simplest answer to your question is No. The easiest way to accomplish what you desire is:

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

The idea is to let enum be individual values and handle the range with logic statements.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文