4

別の SO の質問から次のクラスを取得しました。

    public class Range<T> where T : IComparable<T>
    {
        public T Minimum { get; set; }
        public T Maximum { get; set; }

        public override string ToString() { return String.Format("[{0} - {1}]", Minimum, Maximum); }

        public Boolean IsValid() { return Minimum.CompareTo(Maximum) <= 0; }

        public Boolean ContainsValue(T value)
        {
            return (Minimum.CompareTo(value) <= 0) && (value.CompareTo(Maximum) <= 0);
        }
    }

ただし、このクラスの多くのインスタンスを含む別のクラスを作成し、それらすべてに対して foreach ループを実行して、渡された数値が範囲のいずれかに含まれている場合に true を返すことができるようにしたいと考えています。

    public class Ranges<T> where T : Range<T>
    {
        private List<Range<T>> rangelist;

        public void add(Range<T> range)
        {
            rangelist.Add(range);
        }

        public Boolean ContainsValue(T value)
        {
            foreach (Range<T> range in rangelist)
            {
                if (range.ContainsValue(value)) return true;
            }

            return false;
        }
    }

ただし、エラーが発生しますThe type 'T' cannot be used as type parameter 'T' in the generic type or method 'Range<T>'. There is no implicit reference conversion from 'T' to 'System.IComparable<T>'.

ここで何がうまくいかないのですか?

4

3 に答える 3

9

制約は必要ないようですwhere T : Range<T>

同等の制約を繰り返すだけです。

public class Ranges<T> where T : IComparable<T>
{
}
于 2013-08-08T17:50:34.047 に答える
8

2 番目のクラスを少し書き直すと、その理由がわかります。

public class Ranges<U> where U : Range<U>
{
    private List<Range<U>> rangelist;

    public void add(Range<U> range)
    {
        rangelist.Add(range);
    }
    ...
}

Uエラーは、が に変換可能かどうかをコンパイラが認識していないことを示しています。これは、 and (はインターフェイスを実装していません)IComparable<U>の宣言から明らかです。Ranges<U>Range<T>Range<T>

さらに重要なのは、再帰的な一般的な引数があることです!

Uisの場合Range<U>、クラスはRanges<Range<T>>where TisUなどのようになります。

私が言えることから、あなたは書くつもりはありません:

Ranges<Range<int>> x = ...;

むしろ:

Ranges<int> x = ...;

つまり、次のようになります。

public class Ranges<T> where T : IComparable<T>
{
    private List<Range<T>> rangelist;

    ...
于 2013-08-08T17:50:21.390 に答える
1

そのために新しいクラスは必要ありません。linq を使用してください。

list1.All(x=>list2.Any(y=>y == x))

更新:あなたは言っています:しかし、このクラスの多くのインスタンスを含む別のクラスを作成し、それらすべてに対して foreach ループを実行し、渡された数値が範囲のいずれかに含まれている場合は true を返したいと思います:

したがって、効果的にリストのリストがあります。またはより一般的IEnumerableにのIEnumerables.

このシナリオを処理するのに十分な標準の汎用データ構造があります

   public static class ListOfListExtention {

        public static bool ContainAny( this List<List<int>> lists, int number ) {
             return lists.Any(l=>l.Any(x=>x == number))
        }

   }

IComparable インターフェイスを使用して、より一般的な方法で書き直すことができます

   public static class ListOfListExtention {

        public static bool ContainAny<T>
           (this List<List<int>> lists, int value ) where T : IComparable<T> {
             return lists.Any(l=>l.Any(x=>x == value))
        }

   }

したがって、受け入れられた回答と比較するために、拡張メソッドが1つしかないのに、Listを新しいクラスでラップするのはなぜですか。

于 2013-08-08T17:51:27.157 に答える