 So, while enumerations are a very common language construct, they happen to be a very weak construct in most languages. There is some variancy, for instance. Aida does enhance them a little bit, but fundamentally enumerations are really just name number mappings, and there isn't a whole lot of power there. This being said, a lot of the language features that can take enumerations are very useful, and it'd be nice if there was some sort of compromise between that. Well, there is actually. I'm going to be doing this video from a C-sharp perspective, which I know isn't super normal for me, but I have in the past with some other things. The reasons for that is largely two-fold. First, in some of the C-sharp ecosystem, you will see what I'm going to describe within that ecosystem, and the other is that in Aida, this pattern really isn't that necessary. There are other approaches that are generally better. I am talking about the enum class, or enum struct, and it is essentially taking a class or a struct and presenting it in the same sort of way that an enumeration would exist, sort of making it appear with enum semantics. So let's get over to an editor with some demo code, and I'll show you what I mean. I think the best way to explain this would be to start with a basic enumeration, just the standard classic enumeration, and then we'll expand that into ... I'm going to be doing an enum struct. I'll talk a little bit about the difference between an enum struct and an enum class when we get to that, but then also go on to explain sort of the point behind it, like why you'd want to use that pattern, as well as a real-world example to finish it off. So we have just that basic enumeration. I'm not being particularly creative with it, so it's just called enum, and there's just the three values for second and third. And for the program, we just have a variable that we assign, one of the enumeration values, and then we switch over it, taking an action depending on what the value is. Now of course, the way this code is set up, it's always going to be first value, and we can run this, and you'll see that we do get that result. There we go. I don't know why that text printed really slowly, but okay. So since we're going to expand this now, I could just go ahead and remove that. We won't need that anymore. And to save some time, I have already pre-implemented this. In its most basic form, you really won't want to do this. I'll show, like I said, we'll get to why you want to do this in a little bit, but I just wanted to have the basic one-to-one mapping done first, just so you're not overwhelmed with like, okay, what is all this? Essentially this works through a combination of a constructor that you keep private, a backing field, which again you keep private, and then either a public or internal properties that are the actual values of the enumeration. Now it would be better if these could be defined as constants, however the way things work with C-sharp, this expression is dynamic, not static, so I cannot actually make these constants. There are languages where a constructor like this would still be something you could make constant, so if you're doing this in a language like that, you would certainly want to do so. Now I have implemented this enumeration as a read-only struct specifically. You have two choices, well three really, when doing enumstructs. The basic standard struct is obviously one of them. I would really only recommend that if you happen to be working with older versions of the language that do not support read-only structs. If you are working with a newer version of C-sharp, I would certainly recommend that you use a read-only struct. The semantics just fit a little bit better and the performance winds up usually improving a little bit, although there are obviously edge cases for everything. Ref structs are another possibility although the actual implementation for those gets a little bit different and I'm not going to be dealing with those because that is a whole complicated issue in and of itself, not even delving into like an enumstruct that is a ref struct. That's a complicated matter, you probably don't want to go that route, but I have seen some valid reasons for that. Alternatively, you can implement these as an enum class. There are two reasons that I've seen where that may be something that you do. The first is that at least with C-sharp, every struct has a default constructor that you cannot redefine and you cannot hide away. Even though I have a constructor defined here, there is also another constructor you can call that is public that accepts no properties. Essentially the signature is the problem here is that since we're trying to make this look like enumeration, you only want these, essentially single-tents, just different single-tents, exposed. You don't want the constructor exposed, but it has to be for a struct. One possible way of dealing with that is to just assign a default here, we can do that. I typically recommend going with the first value since that is your standard behavior with enumerations anyways. We don't want to violate the semantics if you can help it. You want to keep as close to that as possible so that it feels as much like an enumeration as possible. With classes, there is no default constructor unless you haven't defined any constructors at all. If this was a class instead, since we have this constructor here, this would be the only constructor that exists for the class at all, and so then we don't have that problem. I don't consider that too much of a problem in practice. Yes, somebody could call a constructor on any enumstruct and it gets a little weird, but as long as you have well-documented code, it should be obvious that the thing should be used as an enumeration, and I find in practice it's just not really that much of an issue. It's more of a theoretical one than anything. But if you are concerned about that, either assigning a default value for the enumstruct or using an enum class instead is one of the reasons why. Another option, although I want to be very careful with this one, is because classes support inheritance, it is possible to do a type of enumeration inheritance where you can extend by adding in values to an enum class. What I want to be careful with for that one is the overwhelming majority of cases where people think they need to extend an enumeration, they have serious design problems that need to be fixed, and extending the enumeration is not actually a good approach. But for the very, very small number of cases where an enum class, where extending an enumeration is actually what you need, enum classes are a way to do that. But in either instance, the reason why you use these is the same. So let's go back over to here, and you can see that of course it's not going to build properly, we need to change these over. And while this assignment doesn't change at all, other than the class name, and normally I recommend you don't change the name of the object at all, we had do for the example. This no longer works. In fact, you cannot switch over a struct. So what do we do about this? This actually gets to the point of enum structs and enum classes, actually. See the idea behind them is since they are a container of sorts, they think that container is sort of the wrong way to describe it, but they're a code grouping of sorts. You can internalize the behavior. If you find yourself switching over an enum and doing the same things throughout many parts of your code, you probably want to implement this pattern. For this example, I mean we just have the one switch statement, but you'll see how this goes and how this can be beneficial. It essentially helps you don't repeat yourself, which is just a good design pattern in general. I suppose we can call this just like write value, so let's do internal void write value, and now what we do is essentially, yeah, I mean we'll essentially copy this. There's a slight change that needs to be made, but that's pretty much it. So we're going to switch over the internal value, and the case statements will just be what the backing value would be for these. Alternatively, if you want to be a little bit more clear, you can also do, and I would actually write. You can't do that in C sharp. Forgot about that. Sorry. It's one of the downsides to programming in different languages is you forget exactly how certain things work. We go back to whether or not these can be constant expressions. If the language you're using allows this kind of thing as a constant expression, then you would be able to do what I was doing there, and I highly recommend doing that if you can. If not, you will have to... I'd suggest doing something like this, and you can copy that into there, and just so that you don't have it hard coded in two different places, you have it hard coded in one place instead and can then change that. For this example, though, we'll just leave these. So now, since we've internalized this behavior, we can go back here and just call D write value. Now if we run this, we still get first value. But conveniently, and what I was alluding to before, we no longer have to create repeated switch statements. We can do something like this. And now we should get first value and third value printed out, and we do. So if you find yourself doing multiple switch case statements over the same enumeration and especially if the behavior you're doing is the same, you probably want to go this route. Now I said I would have a real world example of this, so let's pull one up. Most of you who watch my channel are aware that I am primarily an IDA developer and that I've been working on a collection of tooling for working with the IDA language itself. Part of that, of course, is recognizing handling and working with directives. Now in IDA there are arguably three different types of directives. Progmas and aspects are largely undebated, they're just directives, period, there's complete agreement on that. Arguably certain attributes and their usages of it, specifically the assignment of attributes can be viewed as a type of directive. I don't want to get into that debate here, but inside of this class library is all of the directives that I have defined as of now. Now in many cases, directive only has a few valid things you can assign it to. And the example I'm going to use of that is the IDA version directive. There's four at the time of this video, IDA versions that exist, 83, 95, 2005, and 2012. And to simplify handling of this, instead of doing the IDA version as an enumeration of these four values, I've done it as a, I mean in this case a sealed class. But like I had said, there are also struct variants of this. In fact, I typically use the struct variants, but it's some of the performance details and behavioral details and that stuff. So in this specific case, the backing of this is not an integer, but is actually an enumeration. So that's a little bit different, but this is a viable thing you can do. But it allows us to, one, actually inherit from various interfaces. This is important for the iAspect and iConfiguration progmas, or interfaces, iAspect and iConfiguration progma interfaces, which forces definitions of these right here. See for certain directives, you can use them as either an aspect or a progma. For certain ones, you can use them as both an aspect and a progma. This allows us to get the IDA source code away of representing these directives, depending on which form of that directive we're interested in. And because this is a library meant for reuse, there's numerous people who are going to want to convert the C-sharp representation I've written into that add a source code representation. Internalizing this behavior makes it considerably more convenient for the downstream developers, or for myself writing tools that use these libraries. Hopefully this helps. I've really haven't seen much as far as videos go, covering enumstructs or enum classes, so I really hope this helps out a lot. I know not everybody prefers reading blog posts, and while that is how I learned this, I myself prefer videos, and I know I'm not the only one. So again, I hope this helps. Have a good one.