Question

I have a bunch of code that has lots integers with different meanings (I'd rather a general solution but for a specific example: day-of-the-month vs. month-of-the-year vs. year etc.). I want to be able to overload a class constructor based on these meanings.

For example

int a; // takes role A
int b; // takes role B

var A = new Foo(a);  // should call one constructor
var B = new Foo(b);  // should call another constructor

Now clearly that won't work but if I could define a type (not just an alias) that is an int in all but name like this:

typedef int TypeA;  // stealing the C syntax
typedef int TypeB;

I could do the overloading I need and let the type system keep track of what things are what. In particular this would allow me to be sure that values are not mixed up, for example a value returned from a function as a year is not used as a day-of-the-month.

Is there any way short of class or struct wrappers to do this in c#?


It would be nice if the solution would also work for floats and doubles.

Was it helpful?

Solution

There is no direct typedef equivalent, but you can do the following:

using TypeA = int;
using TypeB = int;

However, this just aliases the type rather than creating a new strong type. Therefore, the compiler will still treat them as an int when resolving method calls.

A better solution might be to create simple wrapper classes that wraps int and provides implicit casting, such as:

struct TypeA
{
   public TypeA(int value)
   {
      this.realValue = value;
   }

   private int realValue;
   public static implicit operator int(TypeA value)
   {
     return this.realValue;
   }

   public static implicit operator TypeA(int value)
   {
     return new TypeA(value);
   }
}

However, in most situations, an enum would be more appropriate.

OTHER TIPS

This may be way off, but couldnt you use an enum for this? Enum base is int, but is typed, and you could define different constructors based on the type of enum passed.

If it's just for the constructor, couldn't you use something like this:

 int dom = 5;
int doy = 100;

Foo b = Foo.NewFromDayoftheMonth(dom);

Foo c = Foo.NewFromDayoftheYear(doy);

where each method are static and create a new Foo object based on the parameters passed in.

This seems like a solution to me, where there isn't much else of one.

I would also create a struct around the value :

public struct TypeA
{
  private int value;
  public TypeA(int value)
  {
    this.value = value;
  }

  public static explicit operator int(TypeA a)
  {
     return a.value;
  }

  public static explicit operator TypeA(int value)
  {
     return new TypeA(value);
  }
}

you can also declare operators to combine types and methods to provide a rich type around the int value.

A Year type can provde a IsLeap property, a day of month can be restraint to values between 1 and 31 and provide a special arithmetic.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top