Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何避免在.NET中为不同的数字类型编写重复代码_C#_F#_Numbers_Dry_Nemerle - Fatal编程技术网

C# 如何避免在.NET中为不同的数字类型编写重复代码

C# 如何避免在.NET中为不同的数字类型编写重复代码,c#,f#,numbers,dry,nemerle,C#,F#,Numbers,Dry,Nemerle,我正在尝试编写通用的Vector2类型,它将与float、double等类型相匹配,并使用算术运算。有没有机会用C#、F#、Nemerle或任何其他或多或少成熟的.NET语言来实现呢 我需要一个解决方案 (1) 良好的表现(与我的写作要求相同) Vector2Float、Vector2Double等类) (2) 这将允许 代码看起来不错(我不想为中的每个类发出代码) (运行时) (3) 这将尽可能多地进行编译时检查 出于原因1和3,我不想使用动力学。现在我正在检查F#和Nemerle UPD

我正在尝试编写通用的Vector2类型,它将与float、double等类型相匹配,并使用算术运算。有没有机会用C#、F#、Nemerle或任何其他或多或少成熟的.NET语言来实现呢

我需要一个解决方案

  • (1) 良好的表现(与我的写作要求相同) Vector2Float、Vector2Double等类)
  • (2) 这将允许 代码看起来不错(我不想为中的每个类发出代码) (运行时)
  • (3) 这将尽可能多地进行编译时检查
出于原因1和3,我不想使用动力学。现在我正在检查F#和Nemerle

UPD:我希望有很多这种类型的数学代码。但是,如果可能的话,我更愿意将代码放在扩展方法中


UPD2:“etc”类型包括int(我实际上怀疑我会使用)和decimal(我想我可能会使用,但现在不会)。使用扩展方法只是一个品味问题——如果有很好的理由不使用,请告诉我。

使用泛型,这也是类型安全的

有关泛型的更多信息:

但您也有可用的数据结构,如和

听起来像你想要的,有很多这样的例子。没有一个真正好的方法只允许十进制、浮点等。你唯一能做的就是限制到struct,但这并不是你想要的。不幸的是,单靠C无法帮助你实现这一点。在运行时发出结构也不会对您有多大帮助,因为您的程序不能静态地引用它们

如果您真的无法复制代码,那么据我所知,“离线”代码生成是实现这一点的唯一方法。不要在运行时生成代码,而是使用
AssemblyBuilder
和friends使用Vector2类型创建一个磁盘上的程序集,或者生成一个C#代码字符串以提供给编译器。我相信一些本机库包装器采用这种方式(即
OpenTK
SharpDX
)。如果要将这些类型合并到手动编码的库中,则可以使用
ilmerge


<>我假设您必须来自C++背景,在这里使用模板很容易实现。但是,您应该问问自己,您是否真的需要基于整数、小数和其他“奇异”数字类型的Vector2类型。您可能也无法基于特定的矢量2参数化其余代码,因此付出的努力可能不值得。

查看内联函数和。

如Daniel所述,F#有一个称为静态解析类型参数的功能,它超出了在C#中使用普通.NET泛型所能做到的。诀窍是,如果你把函数标记为<代码>内联,F ^会自动生成专门的代码(有点像C++模板),然后你可以使用更强大的函数来编写泛型数学。 例如,如果您编写了一个简单的add函数并使其内联:

let inline add x y = x + y;;    
类型推断打印以下类型:

val inline add :
  x: ^a -> y: ^b ->  ^c
    when ( ^a or  ^b) : (static member ( + ) :  ^a *  ^b ->  ^c)
您可以看到推断的类型相当复杂-它指定了一个成员约束,该约束需要两个参数中的一个来定义
+
成员(标准.NET类型也支持这一点)。好的是,这可以完全推断,因此您很少需要编写难看的类型定义


正如评论中提到的,我写了一篇文章,详细介绍了如何在F#中实现这一点。我认为这在C中不容易实现,而在F中编写的内联函数应该只从F中调用(从C中调用它们基本上使用动态)。但是你肯定可以用F#来写你的通用数值计算。

这更直接地解决了你之前的问题。不能将静态成员约束放在结构上,但可以将其放在
静态
创建
方法上

[]

类型Vector2D(x,y)=Vector2D据我所知,您在编译时是一个严格的类型,但您不关心运行时会发生什么。 Nemerle语言目前不支持您想要的这种构造。 但它支持宏,并允许您编写DSL来生成任意代码。 例如,您可以执行一些宏来分析此代码并将其转换为正确的类型

def vec = vector { [1,2] };
假设我们拥有或创建了一个类型向量,代码可以被翻译成

def vec = VectorInt(1,2);
当然,您可以在其中编写任何代码,并将其转换为您想要的任何代码:)

运算符可以像类的常规运算符一样实现。
Nemerle还允许您定义任何运算符,如F#。

这种类型的作用是什么?只是存储数据?或者它也有方法吗?这些方法有什么作用。。。这很重要。什么是“etc”类型?你可能会发现这篇文章很有用::-)顺便说一句:这是一个完全有效的问题,不是前面提到的C#问题的重复。F#有一些东西使它实际上比C#中的要好得多:-)-讽刺的是:看看,它应该可以解决C#中的这个问题。除非我弄错了,否则不可能将泛型参数仅限于数字类型。您是否可以扩展一个考虑到这一点的解决方案(考虑到您在这里所做的只是链接到一个泛型教程)。很抱歉不够具体-我需要一个解决方案,让编译器知道我的类型参数“T”具有静态操作+,-,/,*并最终生成相应的IL指令。@讽刺的是,它们可以,虽然这很不寻常。请看我的答案。@kvb,我仍然无法解决此问题:@ironic:类型是否需要是结构?如果您不必担心默认构造函数,那么实现约束就容易多了。@Daniel,我更喜欢使用struct,原因有二:第一,通常说struct快一点;第二,使用struct,我可以做固定