gpt4 book ai didi

c# - 为什么不能为这个通用的 Clamp 方法推断出类型?

转载 作者:可可西里 更新时间:2023-11-01 03:11:45 24 4
gpt4 key购买 nike

我正在编写一个表示 LED 的类。 r、g 和 b 的基本 3 个 uint 值在 0 到 255 范围内。

我是 C# 的新手,从 uint1 开始,它比我想要的 8 位大。在编写自己的 Clamp 方法之前,我在网上查找了一个并找到了 this great looking answer建议扩展方法。问题是它无法推断类型为 uint。为什么是这样?这段代码上写满了 uint。我必须明确指定类型才能使其正常工作。

class Led
{
private uint _r = 0, _g = 0, _b = 0;

public uint R
{
get
{
return _r;
}
set
{
_r = value.Clamp(0, 255); // nope

_r = value.Clamp<uint>(0, 255); // works
}
}
}

// https://stackoverflow.com/a/2683487
static class Clamp
{
public static T Clamp<T>(this T val, T min, T max) where T : IComparable<T>
{
if (val.CompareTo(min) < 0) return min;
else if (val.CompareTo(max) > 0) return max;
else return val;
}
}

1 一个错误,使用 byte 当然是正确的方法。但我仍然对问题的答案感兴趣。

最佳答案

其他答案是正确的,但这里有一个微妙的地方我认为应该特别指出。

通常在 C# 中,整数文字的类型是 int,但它可以隐式转换为常量在范围内的任何数字类型。因此,即使 int 不能隐式转换为 uint,赋值 myuint = 123; 也是合法的,因为 int 适合。

从这个事实很容易陷入错误的信念,即 int 文字可以在任何需要 uint 的地方使用,但您已经发现了为什么会有这种信念错误的。

类型推断算法是这样的。 (当然,这是一个巨大的简化;lambda 使这变得相当复杂。)

  • 计算参数的类型
  • 分析参数与相应形式参数之间的关系
  • 从该分析中推断出泛型类型参数的类型界限
  • 检查边界的完整性——每个泛型类型参数都必须有边界——和一致性——边界不能矛盾。如果推理不完整或不一致,则该方法不适用。
  • 如果推导类型违反了它们的约束,则该方法不适用。
  • 否则,将具有推导类型的方法添加到用于重载决议的方法集中。

然后,过载解决方案将候选集中的方法相互比较以找到最佳方法。

(请注意,当然没有考虑返回类型;C# 检查是否可以将返回类型分配给分配给它的任何内容重载决策选择了方法之后,而不是在重载期间分辨率。)

在您的情况下,类型推断在“验证是否存在一组一致的边界”步骤中失败。 T 绑定(bind)到 intuint。这是一个矛盾,因此该方法甚至从未添加到要考虑的重载决议的方法集中。 int 参数可转换为uint 的事实从未被考虑过;类型推理引擎仅适用于类型。

类型推断算法也不会在您的场景中以任何方式“回溯”;它没有说“好的,我无法为 T 推断出一致的类型,但也许其中一种类型有效。如果我同时尝试边界 intuint?我们可以看看它们中的任何一个是否真的产生了一种有效的方法。” (它确实做一些类似于涉及 lambda 的事情,这可能导致它在某些情况下尝试任意多种可能的类型组合。)如果推理算法以这种方式工作,那么您将得到结果你想要,但它没有。

基本上,这里的哲学是类型推断算法不是寻求找到使程序运行的任何方法,而是寻找关于派生唯一类型的类型的推理链从论证中得出的信息得出的逻辑结论。 C# 尝试按照用户的意思去做,但也尽量避免猜测;在这种情况下,而不是潜在地猜测错误,它要求您清楚您打算推断的类型。

关于c# - 为什么不能为这个通用的 Clamp 方法推断出类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32716631/

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