Is it better to use Enums or strings?

And why of course

SecnariosScenarios (separate cases):

  1. Roblox enums with guarantee that whatever you need will always have an enum for it, your own custom enums, or just strings?
  2. Your own custom enums because Roblox doesn’t have any or just strings?

TBH I feel like using Roblox Enums are not the way to go because Roblox might not have Enums for everything you need and so you would have to mix and match

Although the possibility of using enums is interesting because you can just quickly see what the different options for the properties are and you can use long names or numbers to reference them so you have a lot of mobility

btw this is from a readability/practicality/scalability/etc pov, not efficiency

2 Likes

Well you can’t make your own actual enums - so in terms of scalability/practicality, they aren’t that great when working with anything custom.

Otherwise, enums in my opinion are great. They’re readable and cover everything that is an actual feature.

In terms of using different enums (KeyCode and UserInputType, for example) for the same purpose - meh. I’d rather just use strings since it looks consistent.

2 Likes

You can make your own Enum module and overwrite the global with a local like this:

local Enum = require(workspace.Enum)

What do you mean by that?

Well there aren’t enums for your own custom features :wink:

There are enums for things like materials, different input types, tweens, etc. all of which are features in the engine.

And that custom Enum weird, that defies logic in my opinion (workspace?) but I guess if it works, it works hehe
I personally dislike overwriting but yeah, if you can do that, why not?

Youre correct to assume that roblox could remove or deprecate enum members at any time.

I opt for making my own Constants/Enums module which can be serialized into numbers or string equivalents

local Constants = {
    Color = {
        RED = Color.fromRGB(255, 0, 0),
    }
}

return Constants

or

local Constants = {
    Status = {
        SUCCESS = "SUCCESS",
        FAILED = "FAILED",
    }
}

return Constants

I’ll usually leave the enums as strings for a while when Im first building and debugging stuff and eventually move it over to numbers especially if I’m sending these over the network.

2 Likes

Why is defining all of the Enums in one script is better than multiple? I would think that you should have all the Enums for a category defined in the handler module that is going to be using them but they will all still be stored in a shared Enum table

In Java, and other languages, you can have the same thing:

public enum Status {
	SUCCESS, FAILED, RUNNING;
}
...
someMethod(Status.SUCCESS);
...
if (status == Status.SUCCESS) {
...

// VS

...
someMethod(1);
...
if (status == 1) {

It’s not necessarily faster (most likely even slower), but it’s much cleaner to look at and use. If you use strings, it’ll be difficult to spot you writing “SUCCES” instead of “SUCCESS” by accident somewhere. If you use roblox Enums (or your own implementation where __index errors for non-existing enums), you’ll get an error if you’re using Status.SUCCES.

Them being defined in one script is just a choice. In Java (and other languages) you also have the choice between having enums in their own file or “embed” them in another class, although the latter is usually only done when that enum is just used for/by that class. The equivalent in Lua would be defining the Enum in a ModuleScript (or _G, if going old school) versus as a local at the top of the script that uses it.

4 Likes

Like einstein said above me, you dont have to store them in one script if you dont want to. I’ll store a lot of general ones together in one script with a bunch of other constants if theyre shared. I’ll also separate them to their own module if I determine it makes more sense for me to do so.

2 Likes

Interesting that you bring up Java as an example… because it’s not recommended to actually use the enum constructor that way in Java given that if you add items the underlying numbering will change and any currently serialized instances of that enum will become incorrect.

4 Likes

if you add items the underlying numbering will change and any currently serialized instances of that enum will become incorrect.

Roblox has quite a history of doing that:

July 19, 2017
	Changed value of enum item JointType.None from 27 to 28
	Changed value of enum item JointType.Rotate from 6 to 7
	Changed value of enum item JointType.RotateP from 7 to 8
	Changed value of enum item JointType.RotateV from 8 to 9
May 10, 2017
	Changed value of enum item ScreenOrientation.Portrait from 1 to 3
	Changed value of enum item ScreenOrientation.Sensor from 2 to 4
March 22, 2017
	Changed value of enum item GraphicsMode.NoGraphics from 6 to 7
March 15, 2017
	Changed value of enum item JointType.None from 22 to 27
December 01, 2016
	Changed value of enum item GridSortOrder.Custom from 2 to 1
	Changed value of enum item GridSortOrder.Name from 1 to 0
November 04, 2016
	Changed value of enum item GraphicsMode.NoGraphics from 5 to 6
April 28, 2016
	Changed value of enum item JointType.None from 13 to 22
February 18, 2016
	Changed value of enum item Platform.None from 18 to 19
January 07, 2016
	Changed value of enum item UserInputType.None from 16 to 21
July 09, 2015
	Changed value of enum item Platform.None from 4 to 18
April 30, 2015
	Changed value of enum item UserInputState.None from 3 to 4
February 20, 2015
	Changed value of enum item UserInputType.None from 12 to 16
September 18, 2014
	Changed value of enum item UserInputType.None from 10 to 12
July 02, 2014
	Changed value of enum item HumanoidStateType.Running from 10 to 8
June 26, 2014
	Changed value of enum item CameraMode.Classic from 1 to 0
June 05, 2014
	Changed value of enum item CameraMode.Classic from 0 to 1
November 21, 2013
	Changed value of enum item UserInputType.Keyboard from 6 to 8
	Changed value of enum item UserInputType.None from 7 to 10
	Changed value of enum item UserInputType.Touch from 5 to 7
November 17, 2013
	Changed value of enum item HttpContentType.TextPlain from 2 to 3
5 Likes

I don’t know if it’s because of that reason or readability, but a lot of serializers do use the enum names instead of their ordinal (numeric value based on the order they’re defined in). If you don’t remove enums, move them around and only insert new enums at the bottom/end, the underlying values shouldn’t change I think. then there’s also something about backwards compatibility testing and changing (supposedly) static types after release (or at least non-discardable use)

1 Like

Or you could just be like C++ and allow explicit assignment of Enum numbering to avoid the issue entirely:

enum Blah {
    Red = 0xFF0000,
    Green = 0x00FF00,
    Blue = 0x0000FF,
    A = 5,
    B, //will be 6
    C, //will be 7
    UserDefined = 7000
};

Works really nicely.

1 Like

Wouldn’t B be 0 and C be 1?

enum Foo { a, b, c = 10, d, e = 1, f, g = f + c };
//a = 0, b = 1, c = 10, d = 11, e = 1, f = 2, g = 12

http://en.cppreference.com/w/cpp/language/enum

No, in your example, see how d = 11?

For any other enumerator whose definition does not have an initializer, the associated value is the value of the previous enumerator plus one.

Since A is assigned to 5 in my example, B and C will be 6 and 7 respectively.

Oh that is quite interesting, removing A=5 actually makes B the decimal 256 as continued from the hex values. Thought it would have to be in order, but moving A=5 after B is declared indeed makes it jump from 255, 256 to 5 and 6 again.

#include <iostream>
#include <stdio.h>

enum Blah {
    Red = 0xFF0000,
    Green = 0x00FF00,
    Blue = 0x0000FF,
    B,
    A = 5,
    C,
    UserDefined = 7000
};

int main(){
    Blah b = B;
    Blah c = C;
    std::cout << b << " and " << c; // 256 and 6
    return 0;
}
2 Likes