我正在用 C# 实现玩具语言的解释器,为了用该语言进行数学计算,我想实现如下函数:
public static object Add( object a, object b )
{
// return the sum of a and b
// each might be int, double, or one of many other numeric types
}
我可以想象这个函数的一个非常愚蠢和糟糕的实现,它有大量基于 a 和 b 类型的分支(使用 is 运算符)和一堆强制转换,但我的直觉是有更好的方法。
您认为该功能的良好实现方式是什么?
最佳答案
如果:
- 您只需要一个易于编程的解决方案
- 你的小语言有和 C# 一样的算术规则
- 你可以使用 C# 4
- 您并不特别关心性能
那么你可以简单地这样做:
public static object Add(dynamic left, dynamic right)
{
return left + right;
}
完成。调用此方法时会发生什么,代码将再次启动 C# 编译器 并询问编译器“如果必须添加这两个东西,你会怎么做,但你知道它们的运行时类型编译时间?” (然后动态语言运行时将缓存结果,以便下次有人尝试将两个整数相加时,编译器不会再次启动,它们只是重新使用编译器返回给 DLR 的 lambda。)
如果你想实现自己的加法规则,欢迎来到我的世界。没有什么神奇的方法可以避免大量的类型检查和转换。确实有 数百 两种任意类型相加的可能情况,您必须检查所有情况。
我们在 C# 中处理这种复杂性的方法是在较小的类型子集上定义加法运算符:int、uint、long、ulong、decimal、double、float、所有枚举、所有委托(delegate)、字符串和所有可为 null 的版本这些值类型。 (然后将枚举视为它们的基础类型,这进一步简化了事情。)
例如,当您将 ushort 添加到 short 时,我们通过说 ushort 和 short 都是 int 的特例来简化问题,然后解决添加两个 int 的问题。这大大减少了我们必须编写的代码量。但请相信我,C# 中的二元运算符重载解析算法有数千行代码。这不是一个简单的问题。
如果您的玩具语言旨在成为具有自己规则的动态语言,那么您可以考虑实现 IDynamicMetaObjectProvider 并使用 DLR 机制来实现算术和函数调用等其他操作。
关于c# - C# 中任意对象的数学运算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3355819/