Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8462093
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 10, 20262026-06-10T14:04:26+00:00 2026-06-10T14:04:26+00:00

A somewhat little-known feature of C# is the possibility to create implicit or explicit

  • 0

A somewhat little-known feature of C# is the possibility to create implicit or explicit user-defined type conversions.
I have been writing C# code for 6 years now, and I have never used it. So, I’m afraid I might be missing good opportunities.

What are legitimate, good uses of user-defined conversions? Do you have examples where they are better than just defining a custom method?

—

Turns out, Microsoft has some design guidelines about conversions, the most relevant of which is:

Do not provide a conversion operator if such conversion is not clearly
expected by the end users.

But when is a conversion “expected”? Outside of toy number classes, I can’t figure out any real-world use case.


Here’s a summary of the examples provided in the answers:

  • Radians/Degrees/double
  • Polar/Point2D
  • Kelvin/Farenheit/Celsius

The pattern seems to be: implicit conversions are mostly (only?) useful when defining numerical/value types, the conversion being defined by a formula. In retrospect this is kind of obvious. Still, I wonder if non-numerical classes could also benefit from implicit conversions..?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-10T14:04:27+00:00Added an answer on June 10, 2026 at 2:04 pm

    As mentioned in the comments, degrees and rotations are a good example to avoid mixing up double values, especially between APIs.

    I pulled out the Radians and Degrees classes we’re currently using and here they are. Taking a look at them now (after so long) I want to clean them up (especially the comments/documentation) and make sure they’re properly tested. Thankfully, I’ve managed to get time in the scheduling to do so. At any rate, use these at your own risk, I can’t guarantee if all the math here is correct as I’m pretty sure we haven’t actually used/tested all the functionality we wrote in.

    Radians

    /// <summary>
    /// Defines an angle in Radians
    /// </summary>
    public struct Radians
    {
        public static readonly Radians ZERO_PI = 0;
        public static readonly Radians ONE_PI = System.Math.PI;
        public static readonly Radians TWO_PI = ONE_PI * 2;
        public static readonly Radians HALF_PI = ONE_PI * 0.5;
        public static readonly Radians QUARTER_PI = ONE_PI * 0.25;
        
        #region Public Members
    
        /// <summary>
        /// Angle value
        /// </summary>
        public double Value;
        /// <summary>
        /// Finds the Cosine of the angle
        /// </summary>
        public double Cos
        {
            get
            {
                return System.Math.Cos(this);
            }
        }
        /// <summary>
        /// Finds the Sine of the angle
        /// </summary>
        public double Sin
        {
            get
            {
                return System.Math.Sin(this);
            }
        }
    
        #endregion
    
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="value">angle value in radians</param>
        public Radians(double value)
        {
            this.Value = value;
        }
        /// <summary>
        /// Gets the angle in degrees
        /// </summary>
        /// <returns>Returns the angle in degrees</returns>
        public Degrees GetDegrees()
        {
            return this;
        }
    
        public Radians Reduce()
        {
            double radian = this.Value;
            bool IsNegative = radian < 0;
            radian = System.Math.Abs(radian);
            while (radian >= System.Math.PI * 2)
            {
                radian -= System.Math.PI * 2;
            }
            if (IsNegative && radian != 0)
            {
                radian = System.Math.PI * 2 - radian;
            }
            return radian;
        }
    
        #region operator overloading
    
        /// <summary>
        /// Conversion of Degrees to Radians
        /// </summary>
        /// <param name="deg"></param>
        /// <returns></returns>
        public static implicit operator Radians(Degrees deg)
        {
            return new Radians(deg.Value * System.Math.PI / 180);
        }
        /// <summary>
        /// Conversion of integer to Radians
        /// </summary>
        /// <param name="i"></param>
        /// <returns></returns>
        public static implicit operator Radians(int i)
        {
            return new Radians((double)i);
        }
        /// <summary>
        /// Conversion of float to Radians
        /// </summary>
        /// <param name="f"></param>
        /// <returns></returns>
        public static implicit operator Radians(float f)
        {
            return new Radians((double)f);
        }
        /// <summary>
        /// Conversion of double to Radians
        /// </summary>
        /// <param name="dbl"></param>
        /// <returns></returns>
        public static implicit operator Radians(double dbl)
        {
            return new Radians(dbl);
        }
        /// <summary>
        /// Conversion of Radians to double
        /// </summary>
        /// <param name="rad"></param>
        /// <returns></returns>
        public static implicit operator double(Radians rad)
        {
            return rad.Value;
        }
        /// <summary>
        /// Add Radians and a double
        /// </summary>
        /// <param name="rad"></param>
        /// <param name="dbl"></param>
        /// <returns></returns>
        public static Radians operator +(Radians rad, double dbl)
        {
            return new Radians(rad.Value + dbl);
        }
        /// <summary>
        /// Add Radians to Radians
        /// </summary>
        /// <param name="rad1"></param>
        /// <param name="rad2"></param>
        /// <returns></returns>
        public static Radians operator +(Radians rad1, Radians rad2)
        {
            return new Radians(rad1.Value + rad2.Value);
        }
        /// <summary>
        /// Add Radians and Degrees
        /// </summary>
        /// <param name="rad"></param>
        /// <param name="deg"></param>
        /// <returns></returns>
        public static Radians operator +(Radians rad, Degrees deg)
        {
            return new Radians(rad.Value + deg.GetRadians().Value);
        }
        /// <summary>
        /// Sets Radians value negative
        /// </summary>
        /// <param name="rad"></param>
        /// <returns></returns>
        public static Radians operator -(Radians rad)
        {
            return new Radians(-rad.Value);
        }
        /// <summary>
        /// Subtracts a double from Radians
        /// </summary>
        /// <param name="rad"></param>
        /// <param name="dbl"></param>
        /// <returns></returns>
        public static Radians operator -(Radians rad, double dbl)
        {
            return new Radians(rad.Value - dbl);
        }
        /// <summary>
        /// Subtracts Radians from Radians
        /// </summary>
        /// <param name="rad1"></param>
        /// <param name="rad2"></param>
        /// <returns></returns>
        public static Radians operator -(Radians rad1, Radians rad2)
        {
            return new Radians(rad1.Value - rad2.Value);
        }
        /// <summary>
        /// Subtracts Degrees from Radians
        /// </summary>
        /// <param name="rad"></param>
        /// <param name="deg"></param>
        /// <returns></returns>
        public static Radians operator -(Radians rad, Degrees deg)
        {
            return new Radians(rad.Value - deg.GetRadians().Value);
        }
    
    
        #endregion
    
        public override string ToString()
        {
            return String.Format("{0}", this.Value);
        }
    
        public static Radians Convert(object value)
        {
            if (value is Radians)
                return (Radians)value;
            if (value is Degrees)
                return (Degrees)value;
    
            return System.Convert.ToDouble(value);
        }
    }
    

    Degrees

    public struct Degrees
    {
        public double Value;       
    
        public Degrees(double value) { this.Value = value; }
    
        public Radians GetRadians()
        {
            return this;
        }
    
        public Degrees Reduce()
        {
            return this.GetRadians().Reduce();
        }
    
        public double Cos
        {
            get
            {
                return System.Math.Cos(this.GetRadians());
            }
        }
    
        public double Sin
        {
            get
            {
                return System.Math.Sin(this.GetRadians());
            }
        }
    
        #region operator overloading
    
        public static implicit operator Degrees(Radians rad)
        {
            return new Degrees(rad.Value * 180 / System.Math.PI);
        }
    
        public static implicit operator Degrees(int i)
        {
            return new Degrees((double)i);
        }
    
        public static implicit operator Degrees(float f)
        {
            return new Degrees((double)f);
        }
    
        public static implicit operator Degrees(double d)
        {
            return new Degrees(d);
        }
    
        public static implicit operator double(Degrees deg)
        {
            return deg.Value;
        }
    
        public static Degrees operator +(Degrees deg, int i)
        {
            return new Degrees(deg.Value + i);
        }
    
        public static Degrees operator +(Degrees deg, double dbl)
        {
            return new Degrees(deg.Value + dbl);
        }
    
        public static Degrees operator +(Degrees deg1, Degrees deg2)
        {
            return new Degrees(deg1.Value + deg2.Value);
        }
    
        public static Degrees operator +(Degrees deg, Radians rad)
        {
            return new Degrees(deg.Value + rad.GetDegrees().Value);
        }
    
        public static Degrees operator -(Degrees deg)
        {
            return new Degrees(-deg.Value);
        }
    
        public static Degrees operator -(Degrees deg, int i)
        {
            return new Degrees(deg.Value - i);
        }
    
        public static Degrees operator -(Degrees deg, double dbl)
        {
            return new Degrees(deg.Value - dbl);
        }
    
        public static Degrees operator -(Degrees deg1, Degrees deg2)
        {
            return new Degrees(deg1.Value - deg2.Value);
        }
    
        public static Degrees operator -(Degrees deg, Radians rad)
        {
            return new Degrees(deg.Value - rad.GetDegrees().Value);
        }
    
        #endregion
    
        public override string ToString()
        {
            return String.Format("{0}", this.Value);
        }
    
        public static Degrees Convert(object value)
        {
            if (value is Degrees)
                return (Degrees)value;
            if (value is Radians)
                return (Radians)value;
    
            return System.Convert.ToDouble(value);
        }
    }
    

    Some sample usage

    These really benefit when being used an an API. While, internally, your organization might decide to strictly stick with degrees or radians to avoid mixups, at least with these classes you can use the type that makes the most sense. For example, publicly consumed APIs or GUI APIs can use Degrees whereas your heavy math/trig or internal usage might use Radians. Considering the following classes/print function:

    public class MyRadiansShape
    {
        public Radians Rotation { get; set; }
    }
    
    public class MyDegreesShape
    {
        public Degrees Rotation { get; set; }
    }
    
    public static void PrintRotation(Degrees degrees, Radians radians)
    {
        Console.WriteLine(String.Format("Degrees: {0}, Radians: {1}", degrees.Value, radians.Value));
    }
    

    Yeah, the code is pretty contrived (and terribly ambiguous) but that’s OK! Just goes to show how it can help reduce accidental mixups.

    var radiansShape = new MyRadiansShape() { Rotation = Math.PI / 2}; //prefer "Radians.HALF_PI" instead, but just as an example
    var degreesShape = new MyDegreesShape() { Rotation = 90 };
    
    PrintRotation(radiansShape.Rotation, radiansShape.Rotation);
    PrintRotation(degreesShape.Rotation, degreesShape.Rotation);
    PrintRotation(radiansShape.Rotation + degreesShape.Rotation, radiansShape.Rotation + degreesShape.Rotation);
    
    //Degrees: 90, Radians: 1.5707963267949
    //Degrees: 90, Radians: 1.5707963267949
    //Degrees: 180, Radians: 3.14159265358979
    

    Then they can be really useful for implementing other mathematical concepts based on angles, such as polar coordinates:

    double distance = 5;
    Polar polarCoordinate = new Polar(distance, (degreesShape.Rotation - radiansShape.Rotation) + Radians.QUARTER_PI);
    Console.WriteLine("Polar Coordinate Angle: " + (Degrees)polarCoordinate.Angle); //because it's easier to read degrees!
    //Polar Coordinate Angle: 45
    

    Then finally, you could implement a Point2D class (or use the System.Windows.Point) with implicit conversions to/from Polar:

    Point2D cartesianCoordinate = polarCoordinate;
    Console.WriteLine(cartesianCoordinate.X + ", " + cartesianCoordinate.Y);
    //3.53553390593274, 3.53553390593274
    

    As I said, I want to take another pass at these classes, and probably eliminate the double implicit conversions to Radians to avoid a couple corner case mixups and compiler ambiguities that are possible. Those were actually there before we created the static ONE_PI, HALF_PI (and so on) fields and we were converting from some multiple of the Math.PI double.

    EDIT: Here’s the Polar class as a demonstration of additional implicit conversions. It takes advantage of the Radians class (and thus its implicit conversions) and the helper methods on it and the Point2D class. I haven’t included it here, but the Polar class can easily implement operators interacting with the Point2D class but those aren’t relevant for this discussion.

    public struct Polar
    {
        public double Radius;
        public Radians Angle;
    
        public double X { get { return Radius * Angle.Cos; } }
        public double Y { get { return Radius * Angle.Sin; } }
    
        public Polar(double radius, Radians angle)
        {
            this.Radius = radius;
            this.Angle = angle;
        }
    
        public Polar(Point2D point)
            : this(point.Magnitude(), point.GetAngleFromOrigin())
        {
        }
    
        public Polar(Point2D point, double radius)
            : this(radius, point.GetAngleFromOrigin())
        {
        }
    
        public Polar(Point2D point, Point2D origin)
            : this(point - origin)
        {
        }
    
        public Point2D ToCartesian()
        {
            return new Point2D(X, Y);
        }
        
        public static implicit operator Point2D(Polar polar)
        {
            return polar.ToCartesian();
        }
    
        public static implicit operator Polar(Point2D vector)
        {
            return new Polar(vector);
        }
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have a somewhat strange issue with visual studio. Almost every time I create
I'm a little knew to SQL & PHP and have been given the task
I'm somewhat new to GTK and very new to Cairo. I've been tasked to
This is somewhat complex (well to me at least). Here is what I have
I am somewhat new to android development and development in general. I have a
I have encountered a problem in my program that has me somewhat stumped. I
Let's say I'm writing a little library in C -- some data structure, say.
So, here is my little problem. Let's say I have a list of buckets
I have been using Grails for the past few months and I really like
This problem is somewhat complicated and I'm in a little over my head. I

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.