Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enum struct? A Value object that behaves like a Enum

Tags:

c#

enums

I am wondering how you would approach this problem

I have two Taxrates that can apply to my products. I specifically want to avoid persisting the Taxrates into the database while still being able to change them in a central place (like Taxrate from 20% to 19% etc).

so I decided it would be great to have them just compiled into my application (It's internal). The problem is that I want to not only to know the Rate but also the Name of the Taxrate.

I could go with an Enum that maps to the value. But then I'd have to create some method that retrieves the German Name of that Taxrate for the English enum-value (I write my code in english, the App is in german).

I thought about just using hardcoded objects to reflect this,

public interface Taxrate
{
    string Name { get; }
    decimal Rate { get; }
}

public class NormalTaxRate : Taxrate
{
    public string Name
    { get { return "Regelsteuersatz"; } }

    public decimal Rate
    { get { return 20m; } }
}

But then I'd have to create some sort of list that holds two instances of those two objects. Doing it static may work, but still I'd have to keep some sort of list. Also I'd have to find a way to map my POCO Domain Object to this, because I doubt NHibernate can instantiate the right Object depending on a value in a field.

It doesn't really feel right, and I think I'm missing something here. Hope somebody has a better solution, I can't think of one.

greetings, Daniel

Ps: also please retag this question if you find something fitting, I can't think of more meaningful tags right now.

like image 791
Tigraine Avatar asked Dec 17 '22 10:12

Tigraine


1 Answers

EDIT: Note that the code here could easily be abbreviated by having a private constructor taking the tax rate and the name. I'm assuming that in real life there might be actual behavioral differences between the tax rates.

It sounds like you want something like Java's enums.

C# makes that fairly tricky, but you can do it to some extent using private constructors and nested classes:

 public abstract class TaxRate
 {
     public static readonly TaxRate Normal = new NormalTaxRate();
     public static readonly TaxRate Whatever = new OtherTaxRate();

     // Only allow nested classes to derive from this - and we trust those!
     private TaxRate() {}

     public abstract string Name { get; }
     public abstract decimal Rate { get; }

     private class NormalTaxRate : TaxRate
     {
         public override string Name { get { return "Regelsteuersatz"; } }
         public override decimal Rate { get { return 20m; } }
     }

     private class OtherTaxRate : TaxRate
     {
         public override string Name { get { return "Something else"; } }
         public override decimal Rate { get { return 120m; } }
     }
 }

You'd probably want some sort of static method in TaxRate to return the right instance based on name or whatever.

I don't know how easily this fits in with NHibernate, but hopefully it will help to some extent...

As noted in the comments, it's pretty ugly - or at least can get pretty ugly when you've got lots of different values. Partial classes can help here:

// TaxRate.cs
public partial abstract class TaxRate
{
    // All the stuff apart from the nested classes
}

// TaxRate.Normal.cs
public partial abstract class TaxRate
{
    private class NormalTaxRate : TaxRate
    {
        public override string Name { get { return "Regelsteuersatz"; } }
        public override decimal Rate { get { return 20m; } }
    }
}

// TaxRate.Other.cs
public partial abstract class TaxRate
{
    private class OtherTaxRate : TaxRate
    {
        public override string Name { get { return "Something else"; } }
        public override decimal Rate { get { return 120m; } }
    }
}

You can then munge the project file to show the nested classes as children of the outer class, as shown in this SO question.

like image 129
Jon Skeet Avatar answered Dec 24 '22 00:12

Jon Skeet