Does anyone know of any examples or code that shows a class or struct that can be used for distance like the DateTime struct? I need to be able to add, subtract, and display the data in feet and inches and using conversion methods just gets messy. A class or struct would be perfect, but I came across nothing in my searches.
+8
A:
Use a struct, but make it immutable (all properties are get-only).
Properties should include at least:
- TotalFeet
- TotalInches
Methods should include at least:
- FromFeet (static)
- FromInches (static)
Declare the private backing field as:
private readonly double _meters;
Edit: Maybe something like this.
public struct Distance : IEquatable<Distance>, IComparable<Distance>
{
private static readonly double MetersPerKilometer = 1000.0;
private static readonly double CentimetersPerMeter = 100.0;
private static readonly double CentimetersPerInch = 2.54;
private static readonly double InchesPerFoot = 12.0;
private static readonly double FeetPerYard = 3.0;
private static readonly double FeetPerMeter = CentimetersPerMeter / (CentimetersPerInch * InchesPerFoot);
private static readonly double InchesPerMeter = CentimetersPerMeter / CentimetersPerInch;
private readonly double _meters;
public Distance(double meters)
{
this._meters = meters;
}
public double TotalKilometers
{
get
{
return _meters / MetersPerKilometer;
}
}
public double TotalMeters
{
get
{
return _meters;
}
}
public double TotalCentimeters
{
get
{
return _meters * CentimetersPerMeter;
}
}
public double TotalYards
{
get
{
return _meters * FeetPerMeter / FeetPerYard;
}
}
public double TotalFeet
{
get
{
return _meters * FeetPerMeter;
}
}
public double TotalInches
{
get
{
return _meters * InchesPerMeter;
}
}
public static Distance FromKilometers(double value)
{
return new Distance(value * MetersPerKilometer);
}
public static Distance FromMeters(double value)
{
return new Distance(value);
}
public static Distance FromCentimeters(double value)
{
return new Distance(value / CentimetersPerMeter);
}
public static Distance FromYards(double value)
{
return new Distance(value * FeetPerYard / FeetPerMeter);
}
public static Distance FromFeet(double value)
{
return new Distance(value / FeetPerMeter);
}
public static Distance FromInches(double value)
{
return new Distance(value / InchesPerMeter);
}
public static Distance operator +(Distance a, Distance b)
{
return new Distance(a._meters + b._meters);
}
public static Distance operator -(Distance a, Distance b)
{
return new Distance(a._meters - b._meters);
}
public static Distance operator -(Distance a)
{
return new Distance(-a._meters);
}
public override bool Equals(object obj)
{
if (!(obj is Distance))
return false;
return Equals((Distance)obj);
}
public bool Equals(Distance other)
{
return this._meters == other._meters;
}
public int CompareTo(Distance other)
{
return this._meters.CompareTo(other._meters);
}
public override int GetHashCode()
{
return _meters.GetHashCode();
}
public override string ToString()
{
return string.Format("{0}[m]", TotalMeters);
}
}
280Z28
2010-03-01 17:48:43
Thanks. I'm looking for a library (or class definition) of this already done with all the happy adding and subtracting and tostring functions. I could write it, but if someone else has done it, why not use that.
Wili
2010-03-01 17:51:21
LOL! I love the private backing field name ;) +1 for saving this in meters!
Reed Copsey
2010-03-01 17:51:35
Sweet! You wouldn't happen to have one that does temperature too, would you? :) Out of curiosity, won't immutability add overhead when adding and subtracting, ala string concatenation?
Jeremy Seghi
2010-03-01 18:22:30
Very nice. I don't know why we just don't use the metric system. It makes a lot more sense.
Wili
2010-03-01 18:43:29
@Jeremy Seghi: Since it's a struct, constructing a new instance consists of initializing a value on the stack. Since the object is backed by a double and the operators do not involve conversions, the overhead of immutability is effectively near zero. I wrote this struct just for this post - you could create a similar one for temperature (if you do, note the use of static fields for the clean unit conversions).
280Z28
2010-03-01 18:47:09
You should use `decimal` instead of `double`. Otherwise you'll (sooner or later) discover that `Distance.FromMeters(1/3) + Distance.FromMeters(1/3) != Distance.FromMeters(2/3)`!
Ronald
2010-03-01 19:40:31
@Ronald: `decimal` has more precision than `double`, but it is still not a full-precision type. This is like complaining that `TimeSpan` is inadequate because the resolution is at most one tick. On a side note, in your particular example the integer division truncates and you'll always have equality.
280Z28
2010-03-01 20:53:11
@280Z28: True, but as `TimeSpan` has a resolution of one tick, why not limit `Distance` to, for example, one centimetre? This should take care of any rounding/conversion loss when comparing distances. As distance has a large scale, using base units and storing the value as an integer, may be a good solution.
Ronald
2010-03-06 18:10:54
@Ronald: If it was stored as an integer, a much better choice is storing it as a `long` in Ångströms, which offers integral representation of both customary and SI units, with a range of over ±922337 km (about the distance to the moon and back).
280Z28
2010-03-06 19:33:45
+7
A:
I've written self-contained unit converter classes before, but I don't know of a good one for .NET that is public.
That being said, it's quite easy to write - Just make a struct that can be constructed from inches or feet, and convertable to both.
public struct Distance
{
private Distance(int inches)
{
this.totalInches = inches;
}
private int totalInches;
public int Inches { get { return this.totalInches % 12; } }
public int Feet { get { return this.totalInches / 12; } }
public static Distance FromInches(int inches)
{
return new Distance(inches);
}
public static Distance FromFeet(int feet)
{
return new Distance(feet * 12);
}
public static Distance FromFeetAndInches(int feet, int inches)
{
return new Distance(feet * 12 + inches);
}
}
Reed Copsey
2010-03-01 17:50:47
Dan Puzey
2010-03-01 17:53:31
Only if you need fractions of an inch - otherwise, it would just slow things down. The OP just specified inches + feet.
Reed Copsey
2010-03-01 19:16:01
A:
public class Length
{
public double Inches { get; set; }
public double Feet
{
get { return Inches / 12.0; }
set { Inches = value * 12.0; }
}
public double Meters
{
get { return Inches / 39.3700787; }
set { Inches = value * 39.3700787; }
}
public double Furlongs
{
get { return Feet / 660.0; }
set { Feet = value * 660.0; }
}
public double Miles
{
get { return Furlongs / 8.0; }
set { Furlongs = value * 8.0; }
}
}
ebpower
2010-03-01 18:48:23