C# 泛型类的隐式转换仅限于某些类型
假设我们对泛型类C# 泛型类的隐式转换仅限于某些类型,c#,.net,generics,implicit-conversion,C#,.net,Generics,Implicit Conversion,假设我们对泛型类Matrix有想法,其中T是数字类型(Complex或double或float,int等) 很自然,我们在C语言中有隐式转换,从float到double,从double到Complex。一般规则是,我们有从较小类型到较大类型的隐式转换。到目前为止还不错 现在假设我们正在实现我们的矩阵类型。由于这种新类型在某种程度上也是数值类型(或者至少它包含数值),因此自然会有从矩阵到矩阵的隐式转换,从矩阵到矩阵等。至少对于乘法等数学运算来说,有这些隐式转换是很好的,然而,这似乎不可能正确实现,
Matrix
有想法,其中T
是数字类型(Complex
或double
或float
,int
等)
很自然,我们在C语言中有隐式转换,从float
到double
,从double
到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();
}
}
公共抽象部分类矩阵
{
///
///隐式地将矩阵转换为双精度复数。
///
公共静态隐式算子矩阵(矩阵)
{
matrix.ToComplex();
}
///
///隐式地将矩阵转换为双精度实数。
///
公共静态隐式算子矩阵(矩阵)
{
矩阵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();
}
}
公共抽象部分类矩阵
{
///
///隐式地将矩阵转换为单精度实数。
///
公共静态隐式算子矩阵(矩阵)
{
矩阵ToDouble();
}
}
有没有办法实现这件事,感觉很自然,所以我认为这应该是可以实现的
目前,我已经创建了一个解决方案,它支持所有类型到最大类型的隐式转换,但不能解决从矩阵
到矩阵
的转换,它只解决到矩阵
的转换
公共抽象部分类矩阵
{
///
///隐式地将矩阵转换为双精度复数。
///
公共静态隐式算子矩阵(矩阵)
{
返回矩阵.Map(x=>
{
if(x是数字复数32)
{
var xc32=(Numerics.Complex32)(object)x;
返回新的Complex64(xc32.Real,xc32.virtual);
}
返回新的Complex64(Convert.ToDouble(x),0);
},0.AllowSkip);
}
}
如果有人对这个问题的背景感兴趣,你可以看看
解决这个问题的另一个选择是使用类似“扩展运算符”(类似于扩展方法)的东西,但这些在C#中不存在。首先,我不确定将泛型与数字基元类型一起使用是否是一个好方法。这是语言中一个非常严重的缺失方面,似乎没有任何计划在短时间内解决它。阅读更多信息
struct
,这很糟糕Add
、Multiply
等功能的IArithmetic
接口,并且您将到处装箱和拆箱,这可能会对性能产生很大影响
你的代码远比这糟糕;因为您似乎缺少T
的通用接口,所以您需要强制转换到对象以使通用强制转换成功
另外,如果您没有类似于if(typeof(t)==typeof(Complex))…
的公共接口代码,那么当使用泛型时,这是一个很大的危险信号;泛型类/方法应该处理无限多的类型,而不仅仅是几个预设类型,这就是泛型的含义Matrix
作为基本类型
public class DoubleMatrix : Matrix<double>
{
//now this is legal
public static implicit operator DoubleMatrix(FloatMatrix matrix)
=> matrix.ToDouble();
}
公共类双矩阵:矩阵
{
//现在这是合法的
公共静态隐式运算符DoubleMatrix(FloatMatrix)
=>matrix.ToDouble();
}
其中
FloatMatrix
显然是FloatMatrix:Matrix
我所知道的创建通用向量或矩阵类并让它执行代数(加法、减法、乘法)的唯一方法是发出调用运算符的MSIL
代码(例如运算符+
)。然后,它可以与任何定义了静态MyType操作符+(MyType a、MyType b)
的类型以及内置类型一起使用
有关更多详细信息,请参阅类似问题
使用操作中的静态方法,您可以获得以下示例代码
public class Matrix<T>
{
T[,] elements;
static readonly Func<T,T> add = Operation<T>.Add;
public static Matrix<T> operator + (Matrix<T> A, Matrix<T> B)
{
Matrix<T> result = new Matrix<T>(rows,cols);
for(int i=0; i<rows; i++)
{
for(int j=0; j<cols; j++)
{
result[i,j] = add(A[i,j], B[i,j]);
}
}
return result;
}
// rest of algebra
}
公共类矩阵
{
T[,]元素;
静态只读Func add=Operation.add;
公共静态矩阵运算器
public class Matrix<T>
{
T[,] elements;
static readonly Func<T,T> add = Operation<T>.Add;
public static Matrix<T> operator + (Matrix<T> A, Matrix<T> B)
{
Matrix<T> result = new Matrix<T>(rows,cols);
for(int i=0; i<rows; i++)
{
for(int j=0; j<cols; j++)
{
result[i,j] = add(A[i,j], B[i,j]);
}
}
return result;
}
// rest of algebra
}