Предположит, у нас есть идея для общего класса Matrix<T>
где T
является числовым типом (Complex
или double
или float
, int
и т.д.).неявного преобразования для общего класса ограничен только к некоторым типам
Естественно, что у нас есть неявное преобразование в C# из float
в double
, от double
к Complex
. Общее правило заключается в том, что мы имеем неявное преобразование из меньшего типа в более крупный. Все идет нормально.
Теперь представьте, что мы реализуем наш тип Matrix<T>
. Поскольку этот новый тип также является числовым (или, по крайней мере, он содержит числовые значения), вполне естественно иметь неявные преобразования от Matrix<float>
до Matrix<double>
, от Matrix<double>
до Matrix<Complex>
и т. Д. По крайней мере, это полезно иметь для математических операций, таких как: умножать, добавлять и т. д. Однако это кажется невозможным для правильной реализации, потому что неявный оператор требует, чтобы по крайней мере один тип был таким же, как класс, который мы его внедряем.
Пример: ниже код не компилируется, даже если он решил разрешить мои проблема.
public abstract partial class Matrix<T>
{
/// <summary>
/// Implicitly converts a matrix to double precision complex numbers.
/// </summary>
public static implicit operator Matrix<Complex64>(Matrix<double> matrix)
{
matrix.ToComplex();
}
/// <summary>
/// Implicitly converts a matrix to double precision real numbers.
/// </summary>
public static implicit operator Matrix<double>(Matrix<float> matrix)
{
matrix.ToDouble();
}
}
Это не будет компилироваться, так как «CS0556 определяемого пользователем преобразование должно преобразовать в или из типа ограждающего» и, скажем, я в порядке с этим, потому что она является частью спецификации языка, но не должна быть там любой другой способ добиться этого?
Например, это тоже не скомпилировано.
public abstract partial class Matrix<double>
{
/// <summary>
/// Implicitly converts a matrix to single precision real numbers.
/// </summary>
public static implicit operator Matrix<double>(Matrix<float> matrix)
{
matrix.ToDouble();
}
}
Есть ли способ достичь этой цели, она кажется естественной, поэтому я думаю, что она должна быть достижимой?
Сейчас я создал обходной путь, который позволяет неявное преобразование для всех типов в самый большой, но это не решает преобразование Matrix<float>
в Matrix<double>
, он решает только преобразования в Matrix<Complex>
.
public abstract partial class Matrix<T>
{
/// <summary>
/// Implicitly converts a matrix to double precision complex numbers.
/// </summary>
public static implicit operator Matrix<Complex64>(Matrix<T> matrix)
{
return matrix.Map(x =>
{
if (x is Numerics.Complex32)
{
var xc32 = (Numerics.Complex32)(object)x;
return new Complex64(xc32.Real, xc32.Imaginary);
}
return new Complex64(Convert.ToDouble(x), 0);
}, Zeros.AllowSkip);
}
}
Если кто-то заинтересован в фоновом режиме вокруг этой проблемы, вы можете взглянуть на https://github.com/mathnet/mathnet-numerics/issues/304
Другой вариант, чтобы решить эту проблему можно было бы использовать что-то вроде «операторов продолжения» (по аналогии с методами расширения), но те не присутствуют в C#.
Честно говоря, как пользователь такого API, я бы боялся неявного подобного характера. Что относительно явных приемов? Будет ли это работать на вас? –
@OndrejTucny Нет, к сожалению, я думаю, что неявный бросок - единственный способ пойти. –