首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >"Double“不会转换为"IComparable<Double>”

"Double“不会转换为"IComparable<Double>”
EN

Stack Overflow用户
提问于 2017-05-15 21:40:49
回答 4查看 887关注 0票数 4

我已经创建了一个模板,它返回数组中最大值的索引。它可以工作,但前提是我传入了一个奇怪的类型列表。

代码语言:javascript
复制
    static public int FindMaxIndex<T>( IEnumerable<IComparable<T>> arr )
    {
        IEnumerator<IComparable<T>> it = arr.GetEnumerator();
        if (!it.MoveNext()) return -1;
        int index = 1, maxIndex = 0;
        IComparable<T> max = it.Current;
        while (it.MoveNext())
        {
            if (max.CompareTo( (T)(it.Current) ) < 0)
            {
                maxIndex = index;
                max = it.Current;
            }
            ++index;
        }
        return maxIndex;
    }

现在使用它:

代码语言:javascript
复制
    List<IComparable<Double>> arr = new List<IComparable<Double>>(); // THIS WORKS
    List<Double> arr = new List<Double>(); // THIS DOESN'T

后面的列表是我想要使用的,它给出了这个编译器错误:

代码语言:javascript
复制
cannot convert from 'System.Collections.Generic.List<double>' to 'System.Collections.Generic.IEnumerable<System.IComparable<double>>'

这怎么可能呢?“IComparable”是一个Double;取自它的定义:

public struct Double : IComparable, IFormattable, IConvertible, IComparable<Double>, IEquatable<Double>

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2017-05-15 23:03:32

我认为其他的答案已经解决了为什么你的代码写成isn't working the way you'd expect,甚至为什么code will fail in some cases。然而,没有一个答案告诉你做你想做的事情的方法:

代码语言:javascript
复制
public static int FindMaxIndex<T>( IEnumerable<T> source ) where T : IComparable<T>
{
    using( var e = source.GetEnumerator() )
    {
        if( !e.MoveNext() ) return -1;

        T maxValue = e.Current;
        int maxIndex = 0;

        for( int i = 1; e.MoveNext(); ++i )
        {
            if( maxValue.CompareTo( e.Current ) < 0 )
            {
                maxIndex = i;
                maxValue = e.Current;
            }
        }

        return maxIndex;
    }
}

因此,我在这里引入了一个通用约束( where T : IComparable<T>)。这告诉编译器,无论T是什么,它都将实现IComparable<T>

另外,我将枚举器放在一个using语句中,这将保证它的Dispose方法被调用。

无论如何,现在当你调用这个方法时,它将直接作用于IEnumerable<double>,甚至会为你推导出类型参数:

代码语言:javascript
复制
var someDoubles = new List<double> { 3, 2, 1 };
Console.WriteLine( FindMaxIndex( someDoubles ) ) // Prints "0";

此外,如果在static类中声明了FindMaxIndex,则可以将this关键字放在源参数前面,使其成为扩展方法:

代码语言:javascript
复制
public static int FindMaxIndex<T>( this IEnumerable<T> source ) where T : IComparable<T>
{
    // ...
}

现在你可以这样调用它:

代码语言:javascript
复制
list.FindMaxIndex()
票数 4
EN

Stack Overflow用户

发布于 2017-05-15 21:48:18

泛型协方差仅在泛型参数为引用类型时有效。因为您有一个值类型作为参数,所以它不能执行任何协变转换。

票数 3
EN

Stack Overflow用户

发布于 2017-05-15 21:49:28

doubleIComparable<double>,但List<double>不是List<IComparable<double>>

它也不能被允许。考虑一下:

代码语言:javascript
复制
private class ScrewItUp : IComparable<double>
{
    public int CompareTo(double value) => 0;
}

List<IComparable<double>> list = new List<double>(); // you propose that this work.
list.Add(new ScrewItUp()); // What's this supposed to do, then?

On可以在接口中包含差异,因此可以将List<string>传递给IEnumerable<object>,但只有当差异中涉及的类型都是引用类型时,才会发生这种情况。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43981095

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档