Skip to content

Instantly share code, notes, and snippets.

@rhwy
Created July 4, 2012 23:02
Show Gist options
  • Save rhwy/4dafaa0252944815f16c to your computer and use it in GitHub Desktop.
Save rhwy/4dafaa0252944815f16c to your computer and use it in GitHub Desktop.
Discussion : Attempt to add units to numbers in C# in a simple and clean way
void Main()
{
var a = (Meter)123 + (Kilometer)2.3 + (Centimeter)1234;
Console.WriteLine(a.ToString());
Console.WriteLine(a.To<Kilometer>().ToString());
Console.WriteLine(a.To<Centimeter>().ToString());
var b = (Meter)2 * (Centimeter)30;
Console.WriteLine(b.ToString());
Console.WriteLine(b.ToSurface<Centimeter>().ToString());
}
/*
Prints:
2435.34 Meters
2.43534 Kilometers
243534 Centimeters
0.6 Squared Meter
6000 Squared Centimeters
*/
public interface IUnit
{
double Value {get;}
string Name {get;}
double Factor {get;}
}
public abstract class Distance : IUnit
{
public abstract double Value {get;}
public abstract string Name {get;}
public abstract double Factor {get;}
public override string ToString()
{
string plural = (Value > 1)?"s":"";
return string.Format("{0} {1}{2}",Value, Name, plural);
}
public Distance To<T> () where T : Distance, new()
{
var initial = (Distance)Activator.CreateInstance(typeof(T),new object[]{Value});
return (Distance)Activator.CreateInstance(typeof(T),new object[]{Value/initial.Factor});
}
}
public class Surface : Distance
{
private double _value;
private string _name;
private double _factor;
public override double Value {get{return _value;}}
public override string Name {get{return _name;}}
public override double Factor {get{return _factor;}}
public Surface()
{
}
public Surface(Distance source)
{
_value = source.Value;
_name = "Squared " + source.Name;
_factor = source.Factor *source.Factor;
}
public Surface(double value, double factor, string name)
{
_value = value;
_name = "Squared " + name;
_factor = factor;
}
public Surface ToSurface<T> () where T : Distance, new()
{
var initial = (Distance)Activator.CreateInstance(typeof(T),new object[]{Value});
return new Surface(Value/(initial.Factor*initial.Factor),initial.Factor,initial.Name);
}
}
public class Surface<T> : Surface where T : Distance
{
private double _value;
private string _name;
private double _factor;
public override double Value {get{return _value;}}
public override string Name {get{return _name;}}
public override double Factor {get{return _factor;}}
public Surface()
{
}
public Surface(T source)
{
_value = source.Value;
_name = "Squared " + source.Name;
_factor = source.Factor *source.Factor;
}
public Surface(double value, double factor, string name)
{
_value = value;
_name = "Squared " + name;
_factor = factor;
}
}
public class Meter : Distance
{
private double _value;
public override double Value {get{return _value;}}
public override string Name {get{return "Meter";}}
public override double Factor {get{return 1;}}
public Meter(double value)
{
_value = value;
}
public static implicit operator Meter(double x)
{
return new Meter(x);
}
public static Meter operator +(Meter c1, Meter c2)
{
return new Meter(c1.Value*c1.Factor + c2.Value*c2.Factor);
}
public static Meter operator -(Meter c1, Meter c2)
{
return new Meter(c1.Value*c1.Factor - c2.Value*c2.Factor);
}
public static Surface operator *(Meter c1, Meter c2)
{
return new Surface<Meter>(new Meter(c1.Value*c1.Factor * c2.Value*c2.Factor));
}
public static double operator /(Meter c1, Meter c2)
{
return (c1.Value*c1.Factor / c2.Value*c2.Factor);
}
}
public class Kilometer : Meter
{
public override string Name {get{return "Kilometer";}}
public override double Factor {get{return 1000;}}
public Kilometer(double value):base(value)
{
}
public static implicit operator Kilometer(double x)
{
return new Kilometer(x);
}
}
public class Centimeter : Meter
{
public override string Name {get{return "Centimeter";}}
public override double Factor {get{return .01;}}
public Centimeter (double value):base(value)
{
}
public static implicit operator Centimeter(double x)
{
return new Centimeter(x);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment