繁体   English   中英

“Double”不会被视为“IComparable” <Double> ”

[英]“Double” doesn't get cast as “IComparable<Double>”

我创建了一个模板,它返回数组中最大值的索引。 它有效,但只有我传入一个奇怪的演员列表。

    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;
    }

现在使用它:

    List<IComparable<Double>> arr = new List<IComparable<Double>>(); // THIS WORKS
    List<Double> arr = new List<Double>(); // THIS DOESN'T

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

cannot convert from 'System.Collections.Generic.List<double>' to 'System.Collections.Generic.IEnumerable<System.IComparable<double>>'

怎么会这样? “双重”是一个可比较的; 取自其定义:

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

我认为其他答案已经解决了为什么你编写的代码没有按照你期望的方式工作 ,甚至在某些情况下代码失败的原因 但是,没有一个答案能告诉你如何做你想做的事:

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> ,甚至为你推导出类型参数:

var someDoubles = new List<double> { 3, 2, 1 };
Console.WriteLine( FindMaxIndex( someDoubles ) ) // Prints "0";

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

public static int FindMaxIndex<T>( this IEnumerable<T> source ) where T : IComparable<T>
{
    // ...
}

现在你可以像这样调用它:

list.FindMaxIndex()

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

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

它也不可能被允许。 考虑:

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>但只有在方差中涉及的类型都是引用类型时才会发生。

Jon Hanna的答案是正确的方向。 下面的代码工作。

double可能是IComparable<double> 但是List<double>不是List<IComparable<double>> 需要在列表中转换每个元素。 你不能投整整个清单。

List<double> list = new List<double>() { 1,5,3};
Console.WriteLine(FindMaxIndex(list.Cast<IComparable<double>>()));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM