gpt4 book ai didi

c# - 动态中的值类型运算符处理是否存在错误?

转载 作者:太空宇宙 更新时间:2023-11-03 17:08:15 25 4
gpt4 key购买 nike

Dynamic 应该能够处理数学而不需要我去思考它,但即使在微不足道的情况下我也会遇到一些问题。考虑这个非常简单的函数::

 public static T DynamicFactorial<T>(T input)
{
dynamic num = input;
dynamic res = 1;
for (; num > 1; res *= num, num -=1) ;
return res;
}

这是一个应该处理任何数字类型并对其执行阶乘的函数。不幸的是,当我尝试计算 DynamicFactorial(5UL) 时,这给了我以下异常:

运算符“*=”不能应用于“int”和“ulong”类型的操作数

请不要说我可以将这段代码变成递归调用,因为这是一个例子。我的问题是,如果您尝试使用 dynamic 来使用一元赋值运算符,那么强制我知道在编译时计算我的类型是没有意义的。一个“潜在”的解决方案是这样做::

  public static T DynamicFactorial<T>(T input)
{
dynamic num = input;
T ONE = (T)(1 as dynamic);
dynamic res = ONE;
for (; num > ONE; res *= num, num -=ONE) ;
return res;
}

这行得通,但天啊,它太丑了,需要我创建一个我计划实际使用的类型的常量,至少可以说这很糟糕。

最佳答案

“动态”的基本设计原则是运行时的分析与编译时的分析完全相同,如果编译器已被赋予运行时类型

因此,让我们对您的代码进行修改:

 ulong input = whatever;
dynamic num = input;
dynamic res = 1;
res = res * num;

这应该在运行时完全表现得好像编译器知道所有标记为“动态”的类型。它的行为应该完全

 ulong input = whatever;
object num = input;
object res = 1;
res = (int)res * (ulong)num;

并且该程序在编译时给出错误,因此逻辑上动态版本在运行时必须给出相同的错误。

Dynamic should be able to handle math without making me have to think about it

绝对不会。这不是动态特性的设计原则。动态功能的目的是简化 C# 代码与旨在与动态语言交互的库中的代码的交互,这些库可以是现代库(例如为 Python 和 Ruby 设计的库),也可以是遗留库(例如为 COM 自动化设计的库)通过 VB6 或 VBScript)。在设计此功能时,我们根本没有考虑对算术表达式的结果进行 VB 样式的类型提升,正如您所发现的那样,它做得很糟糕。

让我非常清楚地说明这一点:动态并不是要使 C# 成为一种动态语言,这似乎就是您所认为的那样。动态是关于使 C# 成为一种静态类型的语言,可以与为动态语言设计的库很好地互操作。如果您想要的是一种具有动态算法的语言,请考虑 Visual Basic 或 Python。

(顺便说一句,有些人可能想知道为什么 int + ulong 在 C# 中不合法。C# 中有七个非提升的数字加法运算符:int+int、uint+uint、long+long、ulong+ ulong, float+float, double+double and decimal+decimal. 在这七种中,哪一个最好?int+int, uint+uint and long+long out 因为 ulong 可能放不下。ulong+ulong out 是因为int 可能是负数。剩下 float、double 和 decimal。Float 比 double 好(因为它更具体)所以 double 消失了。但是将 ulong 转换为 float 既不比将 ulong 转换为 decimal 好也不坏。因为我们这里有歧义,我们会产生错误。如果出于某些奇怪的原因必须将 int 添加到 ulong,请插入一个强制转换来解决歧义。)

最后,我注意到有很多方法可以做你想做的事。我还没有真正尝试过,但这可能会奏效:

public static T DynamicFactorial<T>(T input) 
{
dynamic num = input;
dynamic one = default(T);
one++;
dynamic res = one;
while (num > one)
{
res *= num;
num--;
}
return res;
}

这适用于默认值为零且定义了++、-- 和 * 运算符的任何类型。

但是,这是粗暴的、缓慢的,并且是对泛型的滥用。您真的要计算 ushort 的阶乘吗? Factorial 是一个易于定义的函数,您可能不需要超过六个版本。我说的是只写六次,而不是通过滥用泛型和动态来节省少量击键。

关于c# - 动态中的值类型运算符处理是否存在错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3916432/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com