Understanding static implicit operator the right way - c#

I had a brilliant thought, that does not seem to be so brilliant afterwards, but maybe I don't understand the whole thing correctly.
I have a class, that stores some numbers. Some other functions/methods need int's and some need double's. So I thought I can create a class with a precision conversion implicitly.
public class PreciseInteger
{
public double PreciseValue {get; private set;}
public int RoundedValue {get; private set;}
public PreciseInteger(double value)
{
PreciseValue = value;
RoundedValue = (int)Math.Round(value, 0, MidpointRounding.AwayFromZero);
}
public static implicit operator PreciseInteger(int number)
{
return new PreciseInteger(number);
}
public static implicit operator PreciseInteger(double number)
{
return new PreciseInteger(number);
}
public static implicit operator int(PreciseInteger number)
{
return number.RoundedValue;
}
public static implicit operator double(PreciseInteger number)
{
return number.PreciseValue;
}
public override string ToString()
{
return PreciseValue.ToString();
}
}
And the class that uses this class is really a simple property storing class that does not much. So now I use somthing like
double myValue = myClass.StoredValue1 / myDivider;
But here I only get the integer value. I don't want to use an explicit casting (like Convert.ToDouble or (double)). So how could I make sure that the precise value is used and not the rounded one? Or did I misunderstand the whole concept and that doesn't work at all and I would have to use something like MyClass.MyDouble and MyClass.MyInteger values?
Edit: Ok, if I first say int newInt = myClass.StoredValue1 I get a rounded integer and if I use double newDouble = myClass.StoredValue1 I get the precise floating point number. But isn't there a way to say that one of them is always preferred?

The / operator is defined for both int and double:
double operator /(double x, double y);
int operator /(int x, int y);
These two overloads are both applicable when you do:
// assuming myClass.StoredValue1 and myDivider are PreciseIntegers
double myValue = myClass.StoredValue1 / myDivider;
because you defined an implicit conversion to int and an implicit conversion to double. However, the / that takes ints is actually a better function member, because int is a better conversion target, so the compiler always chooses the second overload.
One way to work around this is to define your own / operator for PreciseInteger:
public static PreciseInteger operator /(PreciseInteger number1, PreciseInteger number2) {
return number1.PreciseValue / number2.PreciseValue;
}
Then you can do:
double myValue = myClass.StoredValue1 / myDivider;

Related

Casting an object with a conversion operator fails

So I have this Object, say DoubleContainer.
public struct DoubleContainer
{
private readonly double _value;
private DoubleContainer(double value)
{
_value = value;
}
public static implicit operator double(DoubleContainer doubleContainer)
{
return doubleContainer._value;
}
public static DoubleContainer Create(double value)
{
return new DoubleContainer(value);
}
}
Casting it works as expected in almost all cases, except where it's passed into a function as an Object.
The following code generates an InvalidCastException if I pass in a DoubleContainer:
public double GetDouble(Object input)
{
return (double)input;
}
I can get it to work if I do use dynamic:
public double GetDouble(Object input)
{
return (double)(dynamic)input;
}
My problem with this solution is that Visual Studio grays out the (dynamic), because it should be redundant, so someone may remove it. Also I don't know if there are any other places in the codebase where this same problem may occur.
Is there anything I can do to my implementation of DoubleContainer what will make my first implementation of GetDouble() work? I tried adding another implicit conversion operator from Object to DoubleContainer, but "user-defined conversions to or from a base class are not allowed"....
You cannot make it work, because you can only unbox boxed struct (this is what you are doing with (double) input) to the exact undelying type, for the reasons best described in this article by Eric Lippert. So whenever you do (double) someObject - it will only work if object is actually a double, not int, not float , not DoubleContainer. If you expect other types - you can better use Convert.ToDouble. For that to work with your type you need it to implement IConvertible:
public struct DoubleContainer : IConvertible
{
private readonly double _value;
private DoubleContainer(double value)
{
_value = value;
}
public static implicit operator double(DoubleContainer doubleContainer)
{
return doubleContainer._value;
}
public static DoubleContainer Create(double value)
{
return new DoubleContainer(value);
}
public double ToDouble(IFormatProvider provider) {
return _value;
}
public bool ToBoolean(IFormatProvider provider) {
// delegate to your double
return ((IConvertible) _value).ToBoolean(provider);
}
// ... rest is skipped ...
Then it will work with
public double GetDouble(Object input)
{
return Convert.ToDouble(input);
}
When casting an object to double, compiler does not know that it should call your existing operator double, so it will not insert any call to your user defined operator double.
When you insert dynamic in the middle, compiler will generate something like "if this reference has an operator double, call it`, so it works.
So, it actually cannot work as long as you cast a System.Object to a double, while code suggested by #juharr, slightly modified, will work:
public double GetDouble(Object input)
{
if (input is DoubleContainer)
{
var dc = (DoubleContainer)input;
return (double)dc;
}
return (double)input;
}
EDIT: modified code as per #SergiyKlimkov comment

Implicit operators and a compiler error

I have a class (simplified for the purposes of this question) that wraps a decimal value and uses a couple of implicit operator declarations for converting between the type and the wrapped value:
private class DecimalWrapper
{
public decimal Value { get; private set; }
public DecimalWrapper(decimal value)
{
Value = value;
}
public static implicit operator decimal(DecimalWrapper a)
{
return a != null ? a.Value : default(decimal);
}
public static implicit operator DecimalWrapper(decimal value)
{
return new DecimalWrapper(value);
}
}
The usages of implicit operator here allow things like these to be done:
DecimalWrapper d1 = 5; // uses implicit operator DecimalWrapper
DecimalWrapper d2 = 10;
var result = d1 * d2; // uses implicit operator decimal
Assert.IsTrue(result.Equals(50));
Assert.IsTrue(result == 50);
Now, consider a second class (again, simplified) that has an overloaded constructor that can take a decimal or a DecimalWrapper:
private class Total
{
private readonly DecimalWrapper _total;
public Total(DecimalWrapper total)
{
_total = total;
}
public Total(decimal totalValue)
{
_total = totalValue;
}
}
I would expect to be able to instantiate an instance of Total by passing in an integer value, which would get converted to a decimal:
var total = new Total(5);
However, this results in a compiler error:
The call is ambiguous between the following methods or properties: 'Namespace.Total.Total(TypeTests.DecimalWrapper)' and 'Namespace.Total.Total(decimal)'
To fix this, you have to remove the implicit operator decimal or specify that the value 5 is in fact a decimal:
var total = new Total(5m);
This is all well and good, but I don't see why the implicit operator decimal is relevant here. So, what is going on?
Are you looking for a citation from the language specification?
The cause of this has to do with overload resolution. When you specify an int value as the constructor parameter, no overload is considered "best" because both require a conversion. The specification doesn't consider two levels of conversion different from one level, so the two constructor overloads are equivalent to each other.
As Blorgbeard noted in the comments, you can easily resolve the issue by getting rid of one of the constructors. He suggests removing the DecimalWrapper overload, but since your field is of the DecimalWrapper type, I'd get rid of the decimal overload instead. Doing it this way, if you specify an int value for the constructor, the compiler will implicitly convert to decimal and then DecimalWrapper for you. If you specify a decimal value for the constructor, the compiler will implicity convert to DecimalWrapper for that call, which is what your decimal constructor would have done anyway.
Of course, yet another way to address the issue would be to add other constructors to the Total class, e.g. one that takes an int. Then no conversion is required and the int constructor would be chosen. But this seems like overkill to me.

Can I make this implicit conversion from an operator overload work?

I am trying to overload the division operator in a class to return a double.
I have two classes: Length and Angle. In the Angle class, I have initializers that accept different trigonometric ratios. Here's an example:
public class Angle
{
public double Degrees;
public double Minutes;
public double Etc;
public Angle(double radians)
{
// Main initialization here.
}
public static Angle FromTangent(double tangent)
{
return new Angle(Math.Atan(tangent));
}
}
The Length class converts a measurement input into different units of measure. The last method would really make life easy:
public class Length
{
public double Inches;
public double Feet;
public double Meters;
public double Etc;
public enum Unit { Inch, Foot, Meter, Etc };
public Length(double value, Unit unit)
{
// Main initialization here.
}
public static Length operator /(Length dividend, Length divisor)
{
double meterQuotient = dividend.Meters / divisor.Meters;
return new Length(meterQuotient, Unit.Meter);
}
// This is what I want to be able to do.
public static double operator /(Length dividend, Length divisor)
{
double ratio = dividend.Meters / divisor.Meters;
return ratio;
}
}
The problem is that the last two methods are ambiguous. I did some research, and implicit conversion seems like the right learning path. I have tried the following methods, which do not seem to be in the correct syntax:
public static implicit operator double /(Length dividend, Length divisor) { }
public static double implicit operator /(Length dividend, Length divisor) { }
public static implicit double operator /(Length dividend, Length divisor) { }
Ultimately
I want to be able to divide two Length objects, and get a double. It is only valid for division though, because it returns a ratio, not a number of units. If this is possible, the implementation would be super easy, and awesome. That's why I want to know if this is possible.
Length opposite = new Length(userInputValue, userSelectedUnitOfMeasure);
Length adjacent = new Length(otherInputValue, otherUnitOfMeasure);
Angle angle = Angle.FromTangent(opposite / adjacent); // ← So cool if this is possible
Can this be done while still being able to keep my other division operator overload?
A conversion isn't a division - those are two separate operations. You appear to be trying to combine them at the moment.
Fundamentally, it seems that you should remove this operator:
// Kill this
public static Length operator /(Length dividend, Length divisor)
It simply doesn't make sense - as you mentioned, a length divided by a length is a ratio, it's not a length. 5m / 2m is 2.5, not 2.5m.
Once this is removed, there's no ambiguity, so you're fine.
On the other hand, having fields for inches, feet, metres etc seems like a bad idea to me. You may want to have two fields, one of which is the magnitude and the other of which is the unit (probably an enum).

C#: same-signature methods/constructors and named arguments

Suppose for instance I'm defining a Complex class for representing complex numbers. I would like to define two constructors, so that I can write for example:
Complex z1 = new Complex(x: 4, y: 3);
Complex z2 = new Complex(r: 2, theta: Math.PI / 4);
However, I cannot define the constructors like this:
public Complex(double x, double y) { ... }
public Complex(double r, double theta) { ... }
because both constructors would have the same signature, which is not allowed. But in C# 4 I can write this, using an optional argument:
public Complex(double x, double y) { ... }
public Complex(double r, double theta, bool unused=true) { ... }
It works, I can then use the above constructor calls as intended. The sole purpose of the unused argument is to make the signatures different; it's totally unused, both when defining and when calling the constructor.
To me this seems to be a an ugly trick: is there any better option?
Make the constructor private and have a static factory style function.
public static Complex CreateComplexPolar(double r, double theta);
public static Complex CreateComplex(double x, double y);
You can do validation on the inputs based on what they should be.
Another possibility would be to create a type that encapsulates the inputs and use constructors as you previously mentioned.
public struct PolarCoordinates
{
public double Rho;
public double Theta;
}
public struct CartesianCoordinates
{
public double X;
public double Y;
}
public Complex(PolarCoordinates pc);
public Complex(CartesianCoordinates cc);
Create a static method to create the class, say Complex::FromDouble and Complex::FromDoubleAndTheta.
You can go one step further and make the real constructor private in order to force that construction.
For example, see TimeSpan's FromDays and FromHours.
p.s.
Use better names :)
HTH
The only thing I can think of would be to make one constructor (double, double) and the other could be double, Func.
public Complex(double x, double y) { ... }
public Complex(double r, Func<double> theta) { ... }
It looks like in your example from above that you are doing a calculation and the result of that calculation is the 2nd value for that constructor. If that was always the case then you could just make it a Func parameter instead. Kind of a hack, but it might be better than having an optional 3rd parameter that does nothing.

Creating a Math library using Generics in C#

Is there any feasible way of using generics to create a Math library that does not depend on the base type chosen to store data?
In other words, let's assume I want to write a Fraction class. The fraction can be represented by two ints or two doubles or whatnot. The important thing is that the basic four arithmetic operations are well defined. So, I would like to be able to write Fraction<int> frac = new Fraction<int>(1,2) and/or Fraction<double> frac = new Fraction<double>(0.1, 1.0).
Unfortunately there is no interface representing the four basic operations (+,-,*,/). Has anybody found a workable, feasible way of implementing this?
Here is a way to abstract out the operators that is relatively painless.
abstract class MathProvider<T>
{
public abstract T Divide(T a, T b);
public abstract T Multiply(T a, T b);
public abstract T Add(T a, T b);
public abstract T Negate(T a);
public virtual T Subtract(T a, T b)
{
return Add(a, Negate(b));
}
}
class DoubleMathProvider : MathProvider<double>
{
public override double Divide(double a, double b)
{
return a / b;
}
public override double Multiply(double a, double b)
{
return a * b;
}
public override double Add(double a, double b)
{
return a + b;
}
public override double Negate(double a)
{
return -a;
}
}
class IntMathProvider : MathProvider<int>
{
public override int Divide(int a, int b)
{
return a / b;
}
public override int Multiply(int a, int b)
{
return a * b;
}
public override int Add(int a, int b)
{
return a + b;
}
public override int Negate(int a)
{
return -a;
}
}
class Fraction<T>
{
static MathProvider<T> _math;
// Notice this is a type constructor. It gets run the first time a
// variable of a specific type is declared for use.
// Having _math static reduces overhead.
static Fraction()
{
// This part of the code might be cleaner by once
// using reflection and finding all the implementors of
// MathProvider and assigning the instance by the one that
// matches T.
if (typeof(T) == typeof(double))
_math = new DoubleMathProvider() as MathProvider<T>;
else if (typeof(T) == typeof(int))
_math = new IntMathProvider() as MathProvider<T>;
// ... assign other options here.
if (_math == null)
throw new InvalidOperationException(
"Type " + typeof(T).ToString() + " is not supported by Fraction.");
}
// Immutable impementations are better.
public T Numerator { get; private set; }
public T Denominator { get; private set; }
public Fraction(T numerator, T denominator)
{
// We would want this to be reduced to simpilest terms.
// For that we would need GCD, abs, and remainder operations
// defined for each math provider.
Numerator = numerator;
Denominator = denominator;
}
public static Fraction<T> operator +(Fraction<T> a, Fraction<T> b)
{
return new Fraction<T>(
_math.Add(
_math.Multiply(a.Numerator, b.Denominator),
_math.Multiply(b.Numerator, a.Denominator)),
_math.Multiply(a.Denominator, b.Denominator));
}
public static Fraction<T> operator -(Fraction<T> a, Fraction<T> b)
{
return new Fraction<T>(
_math.Subtract(
_math.Multiply(a.Numerator, b.Denominator),
_math.Multiply(b.Numerator, a.Denominator)),
_math.Multiply(a.Denominator, b.Denominator));
}
public static Fraction<T> operator /(Fraction<T> a, Fraction<T> b)
{
return new Fraction<T>(
_math.Multiply(a.Numerator, b.Denominator),
_math.Multiply(a.Denominator, b.Numerator));
}
// ... other operators would follow.
}
If you fail to implement a type that you use, you will get a failure at runtime instead of at compile time (that is bad). The definition of the MathProvider<T> implementations is always going to be the same (also bad). I would suggest that you just avoid doing this in C# and use F# or some other language better suited to this level of abstraction.
Edit: Fixed definitions of add and subtract for Fraction<T>.
Another interesting and simple thing to do is implement a MathProvider that operates on an abstract syntax tree. This idea immediately points to doing things like automatic differentiation: http://conal.net/papers/beautiful-differentiation/
I believe this answers your question:
http://www.codeproject.com/KB/cs/genericnumerics.aspx
Here's a subtle problem that comes with generic types. Suppose an algorithm involves division, say Gaussian elimination to solve a system of equations. If you pass in integers, you'll get a wrong answer because you'll carry out integer division. But if you pass in double arguments that happen have integer values, you'll get the right answer.
The same thing happens with square roots, as in Cholesky factorization. Factoring an integer matrix will go wrong, whereas factoring a matrix of doubles that happen to have integer values will be fine.
First, your class should limit the generic parameter to primitives ( public class Fraction where T : struct, new() ).
Second, you'll probably need to create implicit cast overloads so you can handle casting from one type to another without the compiler crying.
Third, you can overload the four basic operators as well to make the interface more flexible when combining fractions of different types.
Lastly, you have to consider how you are handling arithmetic over and underflows. A good library is going to be extremely explicit in how it handles overflows; otherwise you cannot trust the outcome of operations of different fraction types.
The other approaches here will work, but they have a high performance impact over raw operators. I figured I would post this here for someone who needs the fastest, not the prettiest approach.
If you want to do generic math without paying a performance penalty, then this is, unfortunately, the way to do it:
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T IncrementToMax(T value)
{
if (typeof(T) == typeof(char))
return (char)(object)value! < char.MaxValue ? (T)(object)(char)((char)(object)value + 1) : value;
if (typeof(T) == typeof(byte))
return (byte)(object)value! < byte.MaxValue ? (T)(object)(byte)((byte)(object)value + 1) : value;
// ...rest of the types
}
It looks horrific, I know, but using this method will produce code that runs as fast as possible. The JIT will optimize out all the casts and conditional branches.
You can read the explanation and some additional important details here: http://www.singulink.com/codeindex/post/generic-math-at-raw-operator-speed
.NET 7 introduces a new feature - generic math (read more here and here) which is based on addition of static abstract interface methods. This feature introduces a lot of interfaces which allow to generically abstract over number types and/or math operations:
class Fraction<T> :
IAdditionOperators<Fraction<T>, Fraction<T>, Fraction<T>>,
ISubtractionOperators<Fraction<T>, Fraction<T>, Fraction<T>>,
IDivisionOperators<Fraction<T>, Fraction<T>, Fraction<T>>
where T : INumber<T>
{
public T Numerator { get; }
public T Denominator { get; }
public Fraction(T numerator, T denominator)
{
Numerator = numerator;
Denominator = denominator;
}
public static Fraction<T> operator +(Fraction<T> left, Fraction<T> right) =>
new(left.Numerator * right.Denominator + right.Numerator * left.Denominator,
left.Denominator * right.Denominator);
public static Fraction<T> operator -(Fraction<T> left, Fraction<T> right) =>
new(left.Numerator * right.Denominator - right.Numerator * left.Denominator,
left.Denominator * right.Denominator);
public static Fraction<T> operator /(Fraction<T> left, Fraction<T> right) =>
new(left.Numerator * right.Denominator, left.Denominator * right.Numerator);
}

Categories