What you are looking for is an implicit type conversion method (Microsoft Documentation). As an example, assuming you have a class called 'PositiveFloat' that automatically clamps floats to values >= 0, then you could have the following class layout:
class PositiveFloat
{
public float val = 0.0f;
public PositiveFloat(float f)
{
val = Math.Max(f, 0.0f); //Make sure f is positive
}
//Implicitly convert float to PositiveFloat
public static implicit operator PositiveFloat(float f)
{
return new PositiveFloat(f);
}
//Implicitly convert PositiveFloat back to a normal float
public static implicit operator float(PositiveFloat pf)
{
return pf.val;
}
}
//Usage
PositiveFloat posF = 5.0f; //posF.val == 5.0f
float fl = posF; //Converts posF back to float. fl == 5.0f
posF = -15.0f; //posF.val == 0.0f - Clamped by the constructor
fl = posF; //fl == 0.0f
For this example, you'll also probably want to provide implicit operator methods for +
, -
etc to support float and int arithmetic on this class.
The operators aren't just restricted to core data types like int though, you can implicitly make one class from another just by using '=', but this gets to the point where you need to start judging context. Does Thing t = y;
make sense, or should it be Thing t = new Thing(y);
or even Thing t = y.ConvertToThing();
? That's up to you.
At the core of C#, basic data types like int, float, char etc are implemented at the compiler level just so we have some sort of base to work with. string too, even though it appears like a reference type. How these types work with stuff like operators and such are virtually identical to the implicit operator stuff above though to ensure consistency, as well as allowing you to invent your own 'basic' types entirely in C#.