【发布时间】:2017-01-22 19:22:07
【问题描述】:
假设我们对泛型类 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 不,不幸的是,我认为隐式转换是唯一的方法。
标签: c# .net generics implicit-conversion