Home > Back-end >  Meaning of ENUM as a data type
Meaning of ENUM as a data type

Time:07-08

I keep reading the statement that 'Enumeration is a datatype'(for example see here ). I am trying to understand the meaning of the statement better. So I wrote the following code.

Imports System
Imports System.Enum
Module Program
    Enum colours As Byte
        Red = 5
        Blue
        Green
    End Enum
    Sub Main(args As String())
        Dim c As colours
        Console.WriteLine(c.Red) 'Prints 5
        Console.ReadLine()
    End Sub
End Module

Because the enum has been declared to be of type BYTE it means that the type of the constants associated with the fields of the enum would be of type byte. But this does not really explain the idea of enum as a data type. So i tried defining a variable of the type colours and tried accessing the enumeration members through Dim c As colours and c.Red and it worked. However two questions comes at this point:

  1. c.Red gives a warning message Access of a shared member, enum member or nested type through an instance; qualifying expression will not be evaluated. I understand the first sentence in the warning message but not the second sentence. What would be the qualifying expression in this case which shall not be evaluated -- c.Red works fine??

  2. Although I can access enum mmebers through the variable c, it seems unnecessary because the same thing can be done by writing colours.red. So although the statement Dim c as colours makes the enum look more as a data type it does not seem to be of much use. If that is right, can someone pls give me an example which illustrates in a more realistic manner the idea of enum as a data type.

CodePudding user response:

Your 2. sort of answers your 1.
You are not supposed to do c.Red, you are supposed to do colours.Red, and if you do c.Red you get the warning.

The qualifying expression that will not be evaluated is c.
That is, the compiler will not generate code that accesses the variable c. Evaluating a variable is a trivial read-only action that you may even not consider "evaluation", but if you had e.g.

Sub Main()
    Dim c As colours = SomeFunction(AnotherFunction(), YetAnotherFunction()).Red
End Sub


Function SomeFunction(ByVal a As Integer, ByVal b As String) As colours
    Console.WriteLine("SomeFunction called")
    Return colours.Blue
End Function

Function AnotherFunction() As Integer
    Console.WriteLine("AnotherFunction called")
    Return 42
End Function

Function YetAnotherFunction() As String
    Console.WriteLine("YetAnotherFunction called")
    Return "42"
End Function

then the SomeFunction(AnotherFunction(), YetAnotherFunction()) (this time's "qualifying expression") would be the part is "not evaluated". None of the SomeFunction, AnotherFunction, YetAnotherFunction would be called, and nothing would appear in the console.


The purpose of an enum is to guide your fellow programmers in regard of what values are allowed. When you declare Dim c as colours, you establish what should and shouldn't be stored in c. It is not different from declaring c As Integer so that someone could not store "asd" in it.

Similarly, Dim c As colours = 5 would raise a compile-time error, because 5 is an Integer rather than a colours. So you would be nudged into Dim c A colours = colours.Red.

I assume the error does not show for you because you have Option Strict Off. You should set it to On.

CodePudding user response:

The point of an Enum is to provide a limited list of valid values in a particular scenario. The underlying type is numeric, so it is very efficient for the system to work with, but the field labels are descriptive and make it very easy for the developer to work with. You could use String to make it just as easy for the developer but then you lose the efficiency and you also lose the ability to limit the range of values. Similarly, you could use a numeric data type to retain the efficiency but you then lose the user-friendliness and you also again lose the ability to limit the range of values.

As for using the values, it doesn't make sense to have a field of type colours and then access colours.Red via that field. That would be like having a field of type DateTime and then accessing the DateTime.TryParse method via that field. There would be no logic to that. You assign a DateTime value to the field, you get a DateTime value from the field and you compare that value to other DateTime values, but you access the TryParse method via the type, not an instance of that type. The same goes for a field on an Enum type: you assign a value to it, you get a value from it, you compare that value to other values of the same type but you access the fields of the type via the type itself.

Let's fix your type for a start. Firstly, an Enum is a first class type, just like classes, structures and modules. Don't declare an Enum inside another type. Like any other type, the only good reason to nest an Enum inside another type is if you're going to declare it Private and only use it inside the other type. In your case, create a new code file and declare your Enum in that. Generally speaking, you should have one type per code file. I tend to break that rule with Enums because they are generally very small. For that reason, I have one code file named Enumerations.vb and I declare all my Enums there.

As for the type itself:

Enum Colour
    Red = 5
    Blue
    Green
End Enum

Like all types, the name should begin with an upper-case letter. There's generally no good reason to specify the numeric type because it will default to Integer and that is the most efficient numeric type for the system to deal with. The tiny bit of storage space you save by using Byte or Short is generally pointless. The name should also be singular except in specific cases that I will cover later. I've left in your initialisation of the Red field but generally that's pointless too. Unless the numbers mean something specific beyond the type itself, just accept the defaults.

Generally speaking, a field of an Enum type will contain one value. In this case, a Colour will be either Red or Blue or Green. There are situations where you may want to store composite values though, e.g. a Permissions type where a user can have zero, one or more permissions. In such cases, you should make three changes:

  1. The name should be plural rather than singular.
  2. The Flags attribute should be appliedto the type.
  3. The values should be explicitly set to powers of 2.
<Flags>
Enum Permissions
    Something = 1
    SomethingElse = 2
    YetAnotherThing = 4
End Enum

Consumers of the type should be able to tell whether composite values are supported or not by whether the name is plural or singular. Unfortunately, this rule was not always followed for older types. The Flags attribute will cause the multiple values to be displayed sensibly when you call ToString on a composite value. The powers of 2 mean that each value occupies one and only one bit within a numeric value, so composite values are never ambiguous.

To answer your questions explicitly:

  1. The qualifying expression in c.Red is c. Anything before a dot qualifies what comes after, i.e. there could be a multitude of members named Red but the expression before the dot qualifies exactly which one of those is being referred to. In cases like this, Red is not a member of a specific instance of colours but rather of the colours type itself, so the specific instance you use to qualify is ignored and the type is used.
  2. Why is the concept of a data type harder to grasp here than anywhere else. You have no trouble understanding why someone would want to store a String object in a String variable, do you? You have no trouble understanding why someone would want to store an Integer value in an Integer variable, do you? Why is this any different? Take a look at the MessageBox.Show method and the various Enums that it takes to control how the message is displayed. In your specific example, let's say that you were representing pixels in a TV that can be red, green or blue. Your Pixel class might have a property of type Colour and you can then set that property to Colour.Red, Colour.Green or Colour.Blue. It provides information of a specific type, just like any other type.
  • Related