nul*_*ull 15 c# generics extension-methods
我正在写一个代表LED的课程.基本上uintr,g和b的3个值在0到255的范围内.
我是C#的新手,从uint 1开始,这比我想要的大8位.在编写我自己的Clamp方法之前,我在网上找了一个,发现这个很棒的答案提示了一个扩展方法.问题是它无法推断出类型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;
}
}
Run Code Online (Sandbox Code Playgroud)
1一个错误,使用byte是当然的方式.但我仍然对这个问题的答案感兴趣.
Eri*_*ert 22
其他答案是正确的,但这里有一个微妙的观点,我认为应该特别提出.
通常在C#中,整数文字的类型是int,但它可以隐式转换为常量在范围内的任何数字类型.因此,即使int不能隐式转换uint,分配myuint = 123;也是合法的,因为int适合.
从这个事实来看,很容易陷入错误的信念,即int文字可以在uint预期的任何地方使用,但你已经发现了为什么这种信念是错误的.
类型推断算法是这样的.(这当然是一个大规模的简化; lambdas使这变得更加复杂.)
然后,过载分辨率继续比较候选集中的方法以找到最佳方法.
(注意,返回类型当然没有考虑; C#检查在重载决策选择方法之后是否可以将返回类型分配给它所分配的任何类型,而不是在重载解析期间.)
在您的情况下,类型推断在"验证存在一组一致的边界"步骤中失败.T为界,都int和uint.这是一个矛盾,因此该方法永远不会被添加到用于考虑重载决策的方法集中.从不考虑int论证可转换的事实uint; 类型推理引擎仅适用于类型.
类型推断算法也不会在您的场景中以任何方式"回溯"; 它并没有说"OK,我无法推断一致的类型T,但也许是个别类型的作品之一.如果我都尝试界int和uint?我们可以看到,如果其中任何实际产生一个可行的方法." (它确实做了类似于涉及lambdas时的事情,这可能导致它在某些情况下尝试任意多种类型的类型组合.)如果推理算法以这种方式工作,那么你将得到你想要的结果,但它不会.
基本上,这里的哲学是类型推理算法并不寻求找到使程序工作的任何方法,而是找到关于类型的推理链,这些类型从参数派生的信息中得出唯一的逻辑结论.C#尝试做用户意味着做的事情,但也试图避免猜测; 在这种情况下,而不是可能猜错,它需要你清楚你想要推断的类型.
Dav*_*rno 21
这是因为使用的是0和255,这是int值,而不是uint人.C#中的裸整数始终被视为int值(如果它们适合该int范围).
您正在Clamp使用表单调用uint.Clamp(int, int) => uint.这由编译器转换为Clamp(unit, int, int) => uint.编译器虽然有效地期待Clamp(T, T, T) => T,但它报告错误,因为混合uint和int类型阻止它解决T应该采用的类型.
换行:
_r = value.Clamp(0, 255);
Run Code Online (Sandbox Code Playgroud)
至:
_r = value.Clamp(0U, 255U);
Run Code Online (Sandbox Code Playgroud)
并且代码将编译.该U后缀告诉编译器的数量是一个uint值.