Created
June 15, 2017 12:09
-
-
Save mickvangelderen/6b8c30abc315154b95037a8f9dbd8150 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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