C#泛型比较类型

3
假设我有这样一个函数,它直接来自于ITU H264视频解码方面的内容:
Clip3(x, y, z)
{
   if (z < x) return x;
   else if (z > y) return y;
   else return z;
}

在ITU文档中,伪代码列为“无数据类型”,实质上暗示可以使用任何数值数据类型。可能是byte、int、uint、double、float等。
这段代码可以编译通过,但在2020年是否是最佳方案?
dynamic Clip3(dynamic x, dynamic y, dynamic z)
{
   if (z < x) return x;
   else if (z > y) return y;
   else return z;
}

看看在第一次运行时,在VS2019社区版的即时窗口中会发生什么:

(uint)AVC.AVCChunk.Clip3((uint)1, (uint)2, (uint)3)
error CS0656: Missing compiler required member 'Microsoft.CSharp.RuntimeBinder.Binder.Convert'
Convert.ToUInt32(AVC.AVCChunk.Clip3((uint)1, (uint)2, (uint)3))
error CS0656: Missing compiler required member 'Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create'
Convert.ToUInt32(AVC.AVCChunk.Clip3(1, 2, 3))
error CS0656: Missing compiler required member 'Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create'
AVC.AVCChunk.Clip3(1, 2, 3)
2
(uint)AVC.AVCChunk.Clip3(1, 2, 3)
2

简言之,我有点担心在生产中使用这种方法。是否有更好的替代方案?


我猜更安全的方法是使用IComparable,因为大多数东西都是可比较的。就性能而言,最快的方法是为您需要的每种类型创建一个重载。 - zaitsman
你的意思是可以混合使用类型吗,还是说每个具体调用都会使用相同的三种类型?如果后者成立,最好使用泛型,并限制可选项为值类型。 - insane_developer
我可以接受x、y、z的限制返回类型必须是相同的类型。为byte、char、ushort、short、uint、int等编写重载会很混乱,也不符合DRY原则。以下代码无法编译:T Clip3<T>(T x, T y, T z) where T : IComparable。它仍然会给出“运算符'<'不能应用于类型T和T”的错误提示。 - John Ernest
与T Clip3<T>(T x, T y, T z)相同,其中T:struct,IComparable,不能编译相同的“运算符'<'无法应用于类型T和T。” - John Ernest
1个回答

4

你可以将泛型参数 T 的类型限制为 IComparable<T>,并使用 CompareTo 方法,而不是 <> 运算符:

T Clip3<T>(T x, T y, T z) where T: IComparable<T>
{
   if (z.CompareTo(x) < 0) return x;
   else if (z.CompareTo(y) > 0) return y;
   else return z;
}

搞定了,CompareTo是关键。反映了我期望的类型。因此可以这么说,如果使用IComparable实现泛型,您必须放弃<、>、>=和<=的简写,并用CompareTo进行替换。 - John Ernest
反映到我所期望的类型上。不,这里没有涉及到反射;所有数值类型都有一个特定的IComparable<T>实现。 - Klaus Gütter
我的意思是在我对结果运行了.GetType()之后,它给了我预期的结果,所以没问题,只是想问一下CompareTo是否必要。 - John Ernest
1
@JohnErnest“你可以告别<,>,>=和<=的简写,必须用CompareTo进行替换?”正确的。这些运算符仅对数值类型定义,而非'IComparable<T>'。 - Sweeper
@Sweeper 我也是这么想的,不过还是谢谢你,这让我达到了我需要的目标。 - John Ernest

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接