Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save mickvangelderen/6b8c30abc315154b95037a8f9dbd8150 to your computer and use it in GitHub Desktop.
Save mickvangelderen/6b8c30abc315154b95037a8f9dbd8150 to your computer and use it in GitHub Desktop.
// Some constants, may get them from another place in production code.
internal abstract class Constants {
public const float RadiansPerCircle = 2.0f*(float) System.Math.PI;
public const float DegreesPerCircle = 360.0f;
public const float RadiansPerDegree = RadiansPerCircle/DegreesPerCircle;
public const float DegreesPerRadian = DegreesPerCircle/RadiansPerCircle;
}
public interface IAngularUnit {
float AsRadians { get; }
float AsDegrees { get; }
}
// A struct is used instead of a class because we want a very thin wrapper
// around a float value. In functional programming languages this is usually
// called a `newtype`.
public struct Radians : IAngularUnit {
// The actual value is stored in the radians property.
public float AsRadians { get; }
// The degrees are computer from the radians property every time it is
// requested. If the degrees are requested more commonly than the
// radians, the `Radians` value should be used to store the value
// instead.
public float AsDegrees { get { return AsRadians*Constants.DegreesPerRadian; } }
// The constructor trusts that the passed in float is representing an
// angle in radians.
public Radians(float radians) { this.AsRadians = radians; }
// A static factory method is used instead of a constructor because
// constructors do not support generic parameters. If we would not use
// generics and simply take an IAngle as a parameter, the value has to
// be boxed which is not what we want.
public static Radians From<TAngle>(TAngle angle) where TAngle : IAngularUnit {
return new Radians(angle.AsRadians);
}
}
public struct Degrees : IAngularUnit {
public float AsRadians { get { return AsDegrees*Constants.RadiansPerDegree; } }
public float AsDegrees { get; }
public Degrees(float degrees) { this.AsDegrees = degrees; }
public static Degrees From<TAngle>(TAngle angle) where TAngle : IAngularUnit {
return new Degrees(angle.AsDegrees);
}
}
class Application {
public static void Main() {
PrintInRadians(new Degrees(60.0f));
PrintInRadians(new Radians(3.14f));
PrintInRadiansBoxed(new Degrees(60.0f));
PrintInRadiansBoxed(new Radians(3.14f));
}
public static void PrintInRadians<TAngularUnit>(TAngularUnit angle) where TAngularUnit : IAngularUnit {
// We know the unit of the angle at compile time.
System.Console.WriteLine("{0:F2} rad", angle.AsRadians);
}
public static void PrintInRadiansBoxed(IAngularUnit angle) {
// We know the unit of the angle at run time.
System.Console.WriteLine("{0:F2} rad", angle.AsRadians);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment