C# 使用泛型类型有什么优雅的操作方法吗?
我在一个小的教育项目中工作,我们必须实现一个n维矩阵。根据上下文,此矩阵必须与我们自己的内置C# 使用泛型类型有什么优雅的操作方法吗?,c#,generics,operators,C#,Generics,Operators,我在一个小的教育项目中工作,我们必须实现一个n维矩阵。根据上下文,此矩阵必须与我们自己的内置ComplexNumberstruct或System.Double,对于非常简单的示例,必须与整型(主要是System.Int32)一起使用 由于应用程序的性质,我们不需要实现闪电般的性能 因此,我的第一个想法是实现一个矩阵,其中T需要以某种方式限制为“数字” 这样做的一个明显问题是,目前在语言中没有办法用定义的运算符约束泛型类型T。此外,我没有看到一种简单的方法将T限制为合理的类型 我的问题是: 有人能
ComplexNumber
struct或System.Double
,对于非常简单的示例,必须与整型(主要是System.Int32
)一起使用
由于应用程序的性质,我们不需要实现闪电般的性能
因此,我的第一个想法是实现一个矩阵
,其中T
需要以某种方式限制为“数字”
这样做的一个明显问题是,目前在语言中没有办法用定义的运算符约束泛型类型T
。此外,我没有看到一种简单的方法将T
限制为合理的类型
我的问题是:
我知道实现一个
ComplexMatrix
类型并围绕它为每个矩阵“子类型”(双精度、整数等)创建包装器更容易、更好,并支付复杂类型和矩阵元素碰巧是哪种类型之间转换的性能成本。这个问题更奇怪的是,人们会如何实现类似的场景。实现这一目标的唯一方法是以下几点:
让调用方为所需的运算符指定一个委托并使用这些委托
e、 g:
类矩阵
{
Func_add;
Func _减法;
// ...
公共矩阵(函数加,函数减,…)
{
_添加=添加;
_减法=减法;
// ...
}
}
var m=新矩阵((a,b)=>a+b,(a,b)=>a-b,…);
//假设ComplexNumber有两个静态方法Add和Subtract
var m=新矩阵(ComplexNumber.Add,ComplexNumber.Subtract,…);
但是,我不知道这种方法的性能…这取决于你对什么是优雅的看法。如果你的优雅理念是能够写出
a+b
,其中a
和b
属于泛型,而这就是我的优雅理念,那么这是不可能做到的
遗憾的是,C类泛型不能达到C++模板的优雅,这类代码。
如果Eric读过这个
如果你想引起我的注意,试试我博客上的联系人链接。或者把我的全名写在问题的正文里
这个特性(通过定义的操作符约束泛型类型)是否曾经出现在C#design meetings的假设未来版本中?它是否曾经接近于成为语言
事实上,这是一个经常需要的特性。从C#1.0开始,我们就一直收到这类请求
该功能需要CLR团队的支持,而不仅仅是语言支持——这是我们希望集成到所有语言中的一种功能,这增加了成本
CLR团队已经表示了对此类功能的兴趣,但他们也有很多可以实现的竞争功能,并且实现这些功能的时间和精力有限
实现这种特性的方法有很多种。例如,我们可以添加在接口中指定静态方法的功能:
interface IAddable<T>
{
static T operator+(T x, T y);
}
interface-IAddable
{
静态T算子+(tx,ty);
}
然后
static T Sum<T>(IEnumerable<T> seq) where T : IAddable<T>
{
T sum = default(T);
foreach(T item in seq) sum = sum + item;
return sum;
}
static T Sum(IEnumerable seq),其中T:IAddable
{
T总和=默认值(T);
foreach(序号中的T项)总和=总和+项目;
回报金额;
}
其想法是接口意味着“实现此接口的类型必须具有给定的静态方法”。然后我们将使int自动实现IAddable
,等等
在运行时生成的泛型代码的世界中,如何高效地实现这一点是一个开放的问题
我必须补充一点,这只是一个想法的草图。有很多方法可以实现这种特性。“接口中的静态”概念的用途比数学更广泛,这对我们很有吸引力。如果我们要为这类功能付出巨大的代价,最好有一个真正通用、功能强大的功能,而不是只关注数学
另一方面,完美是善的敌人;最好只是专注于数学问题,而不是寻求更昂贵的通用解决方案
这是一场持续的辩论。这肯定是每个人的雷达屏幕上,但我不希望它在任何时候很快。语言设计人员都埋头研究异步CTP的反馈
像往常一样,Eric对假设的未宣布的未来产品的假设未来语言功能的思考仅用于娱乐目的。一个性能良好的解决方法(仍然很难看)是使用一个封装您想要的算术行为的结构 首先定义一个接口:
public interface IArithmetic<T>
{
T Add(T n1,T n2);
}
最后,将结构作为泛型参数传递到类型:
public class Matrix<T,TArithmetic>
where TArithmetic:struct, IArithmetic<T>
{
private static readonly TArithmetic arithmetic=new TArithmetic();
void DoStuff()
{
arithmetic.Add(1,2);
}
}
公共类矩阵
其中TArithmetic:struct,IArithmetic
{
私有静态只读拟迹算法=新拟迹算法();
void DoStuff()
{
算术加法(1,2);
}
}
我还没有对它进行基准测试,但我怀疑它相当快,因为泛型对传入它的每个值类型都进行了专门化。这就是为什么
double算术
是一种struct
我建议在connect站点上使用这种类型的功能。这将是有趣的看到
public struct DoubleArithmetic:IArithmetic<double>
{
public double Add(double n1,double n2)
{
return n1+n2;
}
}
public class Matrix<T,TArithmetic>
where TArithmetic:struct, IArithmetic<T>
{
private static readonly TArithmetic arithmetic=new TArithmetic();
void DoStuff()
{
arithmetic.Add(1,2);
}
}