AngouriMath icon indicating copy to clipboard operation
AngouriMath copied to clipboard

Complex to implement IConvertible

Open tongbong opened this issue 3 years ago • 5 comments

Hi,

I have a scenario where the return type of a formula is not known in advance. Hence, I would like to write something like this :

Type t = GetTheReturnType(); // ex: typeof(int)
return Convert.ChangeType(resultAsComplex.ToNumber(), t);

This would require the Complex type to implement IConvertible.

public partial record Complex : Number, IConvertible

I noticed that implicit operators for conversion are already in place so implementing the interface is feasible. Anyone has some feedback on this proposition ?

tongbong avatar Apr 14 '21 09:04 tongbong

It will make Number CLS non-compliant. It might be an issue here

WhiteBlackGoose avatar Apr 14 '21 14:04 WhiteBlackGoose

But. We can decompose it into a separate type inheriting from IConvertible, and make an extension method for it.

public sealed class Convertible : IConvertible
{
    internal Convertible(Number number);
    // implementing the interface
}

...

public static Convertible ToConvertible(this Convertible @this) => new(@this);

And as a use case, Convert.ChangeType(resultAsComplex.ToNumber().ToConvertible(), t);

I'll think whether we can do it this way

WhiteBlackGoose avatar Apr 14 '21 15:04 WhiteBlackGoose

It will make Number CLS non-compliant. It might be an issue here

Is CLS still useful in this day and age? I view it as deprecated as Code Access Security. I'd put IConvertible in here as well.

This would require the Complex type to implement IConvertible.

There is no value in implementing that and producing lots of boilerplate. You should just add a

public object Convert(Number x, Type t) =>
    t == typeof(int) ? (int)x
    : t == typeof(long) ? (long)x
    : t == typeof(double) ? (double)x
    : t == typeof(float) ? (float)x
    : t == typeof(short) ? (short)x
    : t == typeof(byte) ? (byte)x
    : t == typeof(uint) ? (uint)x
    : t == typeof(ulong) ? (ulong)x
    : t == typeof(ushort) ? (ushort)x
    : t == typeof(sbyte) ? (sbyte)x
    : t == typeof(string) ? x.Stringize()
    : t == typeof(System.Numerics.Complex) ? (System.Numerics.Complex)x
    : t == typeof(bool) ? x != 0
    : throw new InvalidCastException($"Cannot convert {typeof(Number)} to {t}.");

And you can extend this to include more types than default IConvertible as seen in the System.Numerics.Complex branch. You also get to customise the conversion behaviour!

Happypig375 avatar Apr 14 '21 16:04 Happypig375

Alright, let's keep the issue here for now, until it's 100% clear. @tongbong, for now you can apply the idea with an extension method for your project.

WhiteBlackGoose avatar Apr 16 '21 16:04 WhiteBlackGoose

Yes that is what I did.

tongbong avatar Apr 16 '21 16:04 tongbong