英文:
Cast generic parameter to IComparable<T>
问题
我有一个通用函数,用于检查给定的参数是否是 IComparable<T>,如果是的话则调用适当的方法。但我无法编译代码。
我收到以下消息:
[CS0311] 类型 'System.IComparable<T>' 不能用作泛型类型或方法 'ValueObjectConformanceTestHelper.CheckComparable<T>(T, T, T)' 中的类型参数 'T'。
没有从 'System.IComparable<T>' 到 'System.IComparable<System.IComparable<T>>' 的隐式引用转换。
以下是代码:
void CheckComparable<C>(C a, C b)
where C : IComparable<C>
{
a.CompareTo(b).Should().BePositive();
b.CompareTo(a).Should().BeNegative();
}
void CheckConformance<T>(T a, T b)
{
if (a is IComparable<T> aComp && b is IComparable<T> bComp)
{
this.CheckComparable(aComp, bComp);
}
}
英文:
I have a generic function that checks if given arguments are IComparable<T> and if they are call an appropriate method. But I do not get the code compiled.
I get this message:
[CS0311] The type 'System.IComparable<T>' cannot be used as type parameter 'T'
in the generic type or method 'ValueObjectConformanceTestHelper.CheckComparable<T>(T, T, T)'.
There is no implicit reference conversion from 'System.IComparable<T>'
to 'System.IComparable<System.IComparable<T>>'.
This is the code:
void CheckComparable<C>(C a, C b)
where C : IComparable<C>
{
a.CompareTo(b).Should().BePositive();
b.CompareTo(a).Should().BeNegative();
}
void CheckConformance<T>(T a, T b)
{
if (a is IComparable<T> aComp && b is IComparable<T> bComp)
{
this.CheckComparable(aComp, bComp);
}
}
答案1
得分: 1
技术上,我们可以像这样做:
// 我们希望a与b可比较
void CheckComparable<C>(IComparable<C> a, C b) {
a.CompareTo(b); // 在这里调用它
}
void CheckConformance<T>(T a, T b) {
if (a is IComparable<T> aComp) {
CheckComparable<T>(aComp, b);
}
}
然而,这看起来很奇怪和难读。为什么不传递 IComparer<C>
呢?
void CheckComparable<C>(C a, C b, IComparer<C> comparer = default) {
// 如果没有提供显式的比较器,我们将获得默认的比较器:
// 如果C实现了IComparable<C>,它将基于.CompareTo
comparer ??= Comparer<C>.Default;
// 默认情况下,C不能与自身进行比较,且没有提供比较器
// 所以,我们将此测试从CheckConformance移到这里
if (comparer is null)
return;
// 在这里稍微修改了语法:使用comparer而不是CompareTo
comparer.Compare(a, b); // 在这里调用它
}
void CheckConformance<T>(T a, T b) {
// 这里不需要检查
CheckComparable(a, b);
}
英文:
Technically, we can put something like this:
// We want a be comparable with with b
void CheckComparable<C>(IComparable<C> a, C b) {
a.CompareTo(b); // call this here
}
void CheckConformance<T>(T a, T b) {
if (a is IComparable<T> aComp) {
CheckComparable<T>(aComp, b);
}
}
However, it looks weird and unreadable. Why not pass IComparer<T>
?
void CheckComparable<C>(C a, C b, IComparer<C> comparer = default) {
// If no explicit comparer is provided, we get default one:
// It will be .CompareTo based in case C implements IComparable<C>
comparer ??= Comparer<C>.Default;
// C can't be compared with itself by default and no comparer provided
// So, we move test here from CheckConformance
if (comparer is null)
return;
// Slightly modified syntax here: comparer instead of CompareTo
comparer.Compare(a, b); // call this here
}
void CheckConformance<T>(T a, T b) {
// No check required here
CheckComparable(a, b);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论