Paw*_*oka 5 .net c# generics implicit-conversion
假设我们有一个泛型类的想法Matrix<T>哪里T是数字型(Complex或double或者float,int等).
很自然,我们在C#中从in float到doublefrom 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();
}
}
Run Code Online (Sandbox Code Playgroud)
它不会编译,因为"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();
}
}
Run Code Online (Sandbox Code Playgroud)
有没有办法实现这个目标,感觉很自然,所以我觉得它应该是可以实现的?
目前我已经创建了一种解决方法,可以将所有类型的隐式转换转换为最大类型,但不能解析转换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);
}
}
Run Code Online (Sandbox Code Playgroud)
如果有人对这个问题的背景感兴趣,你可以看看 https://github.com/mathnet/mathnet-numerics/issues/304
解决这个问题的另一个选择可能是使用"扩展运算符"(类似于扩展方法),但C#中不存在这些选项.
首先,我不太确定将泛型与数字基元类型一起使用是一个好的选择。这是该语言的一个非常严重的缺陷,并且似乎没有任何计划在短时间内解决它。阅读此答案以获取更多信息。
struct这是非常糟糕的。对于任何算术支持(如果您要实现矩阵,这是必须的),您需要使用 等定义一个IArithmetic接口Add,Multiply并且您将在各处进行装箱和拆箱,这可能会对性能产生很大影响。
你的代码比那更糟糕;因为您似乎缺少一个通用接口,因为T您需要强制转换为对象才能使通用强制转换成功。
另外,如果您没有类似于if (typeof(T) == typeof(Complex)) ...开始出现的通用接口代码,那么在使用泛型时这是一个很大的危险信号;泛型类/方法应该适用于无限数量的类型,而不仅仅是一些预设类型,这就是泛型的含义。
我认为你应该退后一步,重新考虑你的方法。当语言类型系统似乎在与你作对并且没有提供任何帮助时,这肯定表明你做错了什么。
为什么不简单地实现最大类型的非泛型矩阵呢?复数矩阵。使用浮点型或双精度型矩阵有什么好处?它不能是性能或内存效率,因为任何非通用解决方案都会比您当前的方法更好,所有装箱和拆箱都在进行。
更新:在浏览了您所基于的库之后,我不确定为什么您没有Matrix<T>按照预期使用:作为基本类型。
public class DoubleMatrix : Matrix<double>
{
//now this is legal
public static implicit operator DoubleMatrix(FloatMatrix matrix)
=> matrix.ToDouble();
}
Run Code Online (Sandbox Code Playgroud)
FloatMatrix明明是哪里啊FloatMatrix: Matrix<Float>。
| 归档时间: |
|
| 查看次数: |
485 次 |
| 最近记录: |