I have an entity that can be in one of different states (StateA, StateB and StateC), and in each of them have relevant data of distinct types (TStateA, TStateB, TStateC). Enums in Rust represent this perfectly. What is the best way to implement something like this in C#?
This question may appear similar, but enums in Rust and unions in C are significantly different.
To declare an enumeration, we write the enum keyword, followed by a unique name and a code block. Inside the code block we declare our actual words that will map to numbers, separated by commas. Enums in Rust are conventionally written with pascal case.
An enumeration, or Enum , is a symbolic name for a set of values. Enumerations are treated as data types, and you can use them to create sets of constants for use with variables and properties.
The easiest way to convert an enum to a String in Rust is to implement the std::fmt::Display trait. Then you can call the to_string() method.
In the C# language, enum (also called enumeration) is a user-defined value type used to represent a list of named integer constants. It is created using the enum keyword inside a class, structure, or namespace. It improves a program's readability, maintainability and reduces complexity.
You need a class to represent your Entity
class Entity {States state;}
Then you need a set of classes to represent your states.
abstract class States {
// maybe something in common
}
class StateA : MyState {
// StateA's data and methods
}
class StateB : MyState {
// ...
}
Then you need to write code like
StateA maybeStateA = _state as StateA;
If (maybeStateA != null)
{
- do something with the data in maybeStateA
}
C# does not have a nice way of writing code for this yet, maybe the Pattern Matching that is being considered for C#.next would help.
I think you should rethink your design to use object relationships and containment, trying to take a design that works in rust
and force it into C# may not be the best option.
This might be crazy, but if you are hard-up about emulating Rust-like enums in C#, you could do it with some generics. Bonus: you keep type-safety and also get Intellisense out of the deal! You'll lose a little flexibility with various value types, but I think the safety is probably worth the inconvenience.
enum Option
{
Some,
None
}
class RustyEnum<TType, TValue>
{
public TType EnumType { get; set; }
public TValue EnumValue { get; set; }
}
// This static class basically gives you type-inference when creating items. Sugar!
static class RustyEnum
{
// Will leave the value as a null `object`. Not sure if this is actually useful.
public static RustyEnum<TType, object> Create<TType>(TType e)
{
return new RustyEnum<TType, object>
{
EnumType = e,
EnumValue = null
};
}
// Will let you set the value also
public static RustyEnum<TType, TValue> Create<TType, TValue>(TType e, TValue v)
{
return new RustyEnum<TType, TValue>
{
EnumType = e,
EnumValue = v
};
}
}
void Main()
{
var hasSome = RustyEnum.Create(Option.Some, 42);
var hasNone = RustyEnum.Create(Option.None, 0);
UseTheEnum(hasSome);
UseTheEnum(hasNone);
}
void UseTheEnum(RustyEnum<Option, int> item)
{
switch (item.EnumType)
{
case Option.Some:
Debug.WriteLine("Wow, the value is {0}!", item.EnumValue);
break;
default:
Debug.WriteLine("You know nuffin', Jon Snow!");
break;
}
}
Here's another sample demonstrating the use of a custom reference type.
class MyComplexValue
{
public int A { get; set; }
public int B { get; set; }
public int C { get; set; }
public override string ToString()
{
return string.Format("A: {0}, B: {1}, C: {2}", A, B, C);
}
}
void Main()
{
var hasSome = RustyEnum.Create(Option.Some, new MyComplexValue { A = 1, B = 2, C = 3});
var hasNone = RustyEnum.Create(Option.None, null as MyComplexValue);
UseTheEnum(hasSome);
UseTheEnum(hasNone);
}
void UseTheEnum(RustyEnum<Option, MyComplexValue> item)
{
switch (item.EnumType)
{
case Option.Some:
Debug.WriteLine("Wow, the value is {0}!", item.EnumValue);
break;
default:
Debug.WriteLine("You know nuffin', Jon Snow!");
break;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With