0

IEnumerable<T>.net の新しいバージョンでは、またはを受け入れる拡張メソッドがいくつかありIEnumerableます。そのようなメソッドの 1 つはOfType<TResult>、指定された type にキャストできる元のシーケンスの要素のみを含む列挙型を返すメソッドですTIEnumerableこのメソッドは、元のリストのタイプと宛先のタイプに関係なく、非ジェネリックを使用して元のリストのすべてのアイテムを処理することを完全にうまく処理します。元のリストが であり、 である場合、元のIEnumerable<int>TResultそのまま使用できる場合でもint、元のリストの各項目を非ジェネリックとして取得しobject、キャストしますIEnumerator<int>。元のリストがIEnumerable<int>andTResultの場合StringBuilder、元のリストのすべてのアイテムを宛先タイプにキャストできない場合でも、同様にすべてのアイテムをボックス化します。

IEnumerable<TSrc>を受け取って に変換するメソッドを作成IEnumerable<TResult>し、元の列挙のすべての項目が後者に現れることが保証されている場合、またはソース列挙子の型が後者が空になることを暗示しています(IEnumerableタイプサポートのすべてのバリエーションが同じアイテムのシーケンスを返すと仮定して)?確かに、シーケンスを既に保持している型にキャストしようとすることはそれほど多くありませんが、重複する場合と重複しない場合がある複数の型パラメーターを持つジェネリック クラスを持つことは珍しくありません。

4

1 に答える 1

0

IEquatable<T>.EqualsObject.Equalsオーバーライドと一致する必要があります。具体的IEquatable<T>に直接使用しても価値があるかどうかはわかりません。

ボックス化されたオブジェクトがボックス化されていない値を等価テストに使用することを確認したいだけのように思えます。次のような equals を使用して、必要なことのほとんどを実行できるはずです。

private static bool Equals<T1, T2>(T1 first, T2 second)
{
    // if either are boxed, try Equals with unboxed values (dynamic)
    if (typeof(T2) == typeof(object) && second.GetType().IsValueType)
    {
        dynamic dsec = second;
        if (typeof(T1) == typeof(object) && second.GetType().IsValueType)
        {
            dynamic dfir = first;
            return Equals(dfir, dsec);
        }
        return Equals(first, dsec);
    }
    if (typeof(T1) == typeof(object) && second.GetType().IsValueType)
    {
        dynamic dfir = first;
        Equals<dynamic, T2>(dfir, second);
    }
    // neither are boxed, just fall back to their Equals overrides...
    var t = Object.Equals(first, second);
    return t;
}

Enumerable.Intersect同じタイプのコレクションでExceptのみ機能するため、タイプがそうであった場合は、Object必要なことを行う必要があります。

アップデート:

値型は基本クラスから派生できません。それらの唯一の共通ベースは常にオブジェクトのみです。つまり、比較したい 2 つの型を知っているメソッドを特に使用せずに 2 つの異なる値の型を比較したい場合は、常に少なくとも 1 つの値をボックス化する必要があります。とにかく受け入れない。したがって、さまざまなメソッドを作成しないと不可能です。Enumerable.IntersectExcept

更新 2:

2 つの型を相互に変換できない場合 (または一方を他方に変換できない場合)、それらが等しくなることは決してないことを意味すると仮定するのは不適切な仮定です。例えば:

public struct One
{
    public int Value;
    public override int GetHashCode()
    {
        return Value.GetHashCode();
    }
}

public struct Two
{
    public int Value;
    public override bool Equals(object obj)
    {
        if (obj is Two) return this == (Two)obj;
        if (obj is One) return this.Equals((One)obj);
        return base.Equals(obj);
    }

    public bool Equals(One one)
    {
        return one.Value == Value;
    }

    public static bool operator==(Two one, Two two)
    {
        return one.Value == two.Value;
    }

    public static bool operator !=(Two one, Two two)
    {
        return !(one == two);
    }
    public override int GetHashCode()
    {
        return Value.GetHashCode();
    }
}

// ...

    Console.WriteLine(two.Equals(one));
    Console.WriteLine(two.Equals((Object)one));
    Console.WriteLine(two.GetType().IsAssignableFrom(one.GetType()) || one.GetType().IsAssignableFrom(two.GetType()));

結果は、True、True、および False になります。したがって、明らかに 2 つのオブジェクトは「等しい」場合がありますが、相互に変換することはできません。

于 2012-09-23T18:19:20.167 に答える