Last active
August 9, 2017 16:49
-
-
Save BrianMacIntosh/dbc2689a544cc4782a84616f10d6b45f to your computer and use it in GitHub Desktop.
Shows how type-safe, automatically-converted degree and radian types could be created in C#.
This file contains hidden or 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
using System; | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
AngleDegrees angleA = new AngleDegrees(90); | |
AngleRadians angleB = new AngleRadians(Math.PI / 2); | |
// angleA will be implicitly converted to AngleRadians because that's what the method parameter is | |
double sinD = Sin(angleA); | |
Console.WriteLine(sinD); | |
// angleB is already in radians | |
double sinR = Sin(angleB); | |
Console.WriteLine(sinR); | |
// the return value will be implicitly converted to AngleDegrees | |
AngleDegrees asinD = Asin(0.5); | |
Console.WriteLine(asinD); | |
// the return value is already in radians | |
AngleRadians asinR = Asin(0.5); | |
Console.WriteLine(asinR); | |
// wait to exit | |
Console.ReadLine(); | |
} | |
public static double Sin(AngleRadians angle) | |
{ | |
return Math.Sin(angle.Value); | |
} | |
public static AngleRadians Asin(double value) | |
{ | |
return new AngleRadians(Math.Asin(value)); | |
} | |
/// <summary> | |
/// Structure representing an angle in degrees. | |
/// </summary> | |
public struct AngleDegrees | |
{ | |
public double Value; | |
public AngleDegrees(double angle) | |
{ | |
Value = angle; | |
} | |
/// <summary> | |
/// Converts this angle to radians. | |
/// </summary> | |
public AngleRadians ToRadians() | |
{ | |
return new AngleRadians(Value * Math.PI / 180f); | |
} | |
// Define an implicit conversion from AngleDegrees to AngleRadians. | |
public static implicit operator AngleRadians(AngleDegrees angle) | |
{ | |
return angle.ToRadians(); | |
} | |
// Define math operators on this object | |
// Yeah, this part's a bit of a pain unfortunately | |
// We could also do comparison operators | |
public static AngleDegrees operator *(AngleDegrees a, double b) | |
{ | |
return new AngleDegrees(a.Value * b); | |
} | |
public static AngleDegrees operator /(AngleDegrees a, double b) | |
{ | |
return new AngleDegrees(a.Value / b); | |
} | |
// no implicit addition/subtraction with unidentified doubles | |
public static AngleDegrees operator *(double a, AngleDegrees b) | |
{ | |
return new AngleDegrees(a * b.Value); | |
} | |
public static AngleDegrees operator /(double a, AngleDegrees b) | |
{ | |
return new AngleDegrees(a / b.Value); | |
} | |
// no implicit addition/subtraction with unidentified doubles | |
public static AngleDegrees operator *(AngleDegrees a, AngleDegrees b) | |
{ | |
return new AngleDegrees(a.Value * b.Value); | |
} | |
public static AngleDegrees operator /(AngleDegrees a, AngleDegrees b) | |
{ | |
return new AngleDegrees(a.Value / b.Value); | |
} | |
public static AngleDegrees operator +(AngleDegrees a, AngleDegrees b) | |
{ | |
return new AngleDegrees(a.Value + b.Value); | |
} | |
public static AngleDegrees operator -(AngleDegrees a, AngleDegrees b) | |
{ | |
return new AngleDegrees(a.Value - b.Value); | |
} | |
// can do math with radian and degree objects and have them automatically converted | |
public static AngleDegrees operator *(AngleDegrees a, AngleRadians b) | |
{ | |
return a * b.ToDegrees(); | |
} | |
public static AngleDegrees operator /(AngleDegrees a, AngleRadians b) | |
{ | |
return a.Value / b.ToDegrees(); | |
} | |
public static AngleDegrees operator +(AngleDegrees a, AngleRadians b) | |
{ | |
return a.Value + b.ToDegrees(); | |
} | |
public static AngleDegrees operator -(AngleDegrees a, AngleRadians b) | |
{ | |
return a.Value - b.ToDegrees(); | |
} | |
// can override how this value is converted to a string, too | |
public override string ToString() | |
{ | |
// add the degree sign | |
return Value + "\u00B0"; | |
} | |
} | |
/// <summary> | |
/// Structure representing an angle in radians. | |
/// </summary> | |
public struct AngleRadians | |
{ | |
public double Value; | |
public AngleRadians(double angle) | |
{ | |
Value = angle; | |
} | |
/// <summary> | |
/// Converts this angle to degrees. | |
/// </summary> | |
public AngleDegrees ToDegrees() | |
{ | |
return new AngleDegrees(Value * 180f / Math.PI); | |
} | |
// Define an implicit conversion from AngleRadians to AngleDegrees. | |
public static implicit operator AngleDegrees(AngleRadians angle) | |
{ | |
return angle.ToDegrees(); | |
} | |
// Define math operators on this object | |
// Yeah, this part's a bit of a pain unfortunately | |
// We could also do comparison operators | |
public static AngleRadians operator *(AngleRadians a, double b) | |
{ | |
return new AngleRadians(a.Value * b); | |
} | |
public static AngleRadians operator /(AngleRadians a, double b) | |
{ | |
return new AngleRadians(a.Value / b); | |
} | |
// no implicit addition/subtraction with unidentified doubles | |
public static AngleRadians operator *(double a, AngleRadians b) | |
{ | |
return new AngleRadians(a * b.Value); | |
} | |
public static AngleRadians operator /(double a, AngleRadians b) | |
{ | |
return new AngleRadians(a / b.Value); | |
} | |
// no implicit addition/subtraction with unidentified doubles | |
public static AngleRadians operator *(AngleRadians a, AngleRadians b) | |
{ | |
return new AngleRadians(a.Value * b.Value); | |
} | |
public static AngleRadians operator /(AngleRadians a, AngleRadians b) | |
{ | |
return new AngleRadians(a.Value / b.Value); | |
} | |
public static AngleRadians operator +(AngleRadians a, AngleRadians b) | |
{ | |
return new AngleRadians(a.Value + b.Value); | |
} | |
public static AngleRadians operator -(AngleRadians a, AngleRadians b) | |
{ | |
return new AngleRadians(a.Value - b.Value); | |
} | |
public static AngleRadians operator *(AngleRadians a, AngleDegrees b) | |
{ | |
return a * b.ToRadians(); | |
} | |
public static AngleRadians operator /(AngleRadians a, AngleDegrees b) | |
{ | |
return a / b.ToRadians(); | |
} | |
public static AngleRadians operator +(AngleRadians a, AngleDegrees b) | |
{ | |
return a + b.ToRadians(); | |
} | |
public static AngleRadians operator -(AngleRadians a, AngleDegrees b) | |
{ | |
return a - b.ToRadians(); | |
} | |
// can override how this value is converted to a string, too | |
public override string ToString() | |
{ | |
// show it as a multiple of Pi since that's easier to understand | |
return (Value / Math.PI) + "\u03C0"; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
But see https://codereview.stackexchange.com/questions/39360/type-system-for-different-representations-of-angle-value/39366#39366.