簡體   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