2016-10-06 6 views
0

タイプパラメータを使用するのではなく、タイプインスタンスの引数として希望のタイプを指定する代わりにOfTypeの代替を実装しようとしていますが、それを実装することです。これは私がこれまで持っているものです。Enumerable.OfTypeを実装するTypeインスタンスの引数を持つ<T>を実装する

public static IEnumerable<T> OfType<T>(this IEnumerable<T> enumerable, Type type) 
{ 
    return enumerable.Where(element => type.IsInstanceOfType(element)); 
} 

私は最初に以下のコードで始まったが、それは継承をサポートしません実現...

public static IEnumerable<T> OfType<T>(this IEnumerable<T> enumerable, Type type) 
{ 
    return enumerable.Where(element => element.GetType() == type); 
} 

それから私はのためのベースタイプを比較することについて考えおそらく悪い考えであると思う前に数秒。

私の質問は、指定された型が同じである場合、常にOfTypeと同じ結果を返します。つまり、下のコード例のparametrizedFilteredtypeInstanceFilteredのコレクションには同じ要素が含まれていますか?

IEnumerable<InterfaceType> someCollection = BlackBox.GetCollection(); 
IEnumerable<DerivedType> parametrizedFiltered = someCollection.OfType<DerivedType>(); 
IEnumerable<InterfaceType> typeInstanceFiltered = someCollection.OfType(typeof(DerivedType)); 
+0

あなたは「深い」継承してチェックするためのIsAssignableFrom' 'を見てかかることがあります。 –

+0

@ JeroenvanLangen 'IsAssignableFrom(x.GetType())'は 'null'の場合を無視すると' IsInstanceOfType(x) 'と同等です。 IsAssignableFromの結果をキャッシュすると、パフォーマンスが向上する可能性があります。 – CodesInChaos

+0

配列の共分散型とNULL値型の型は同じです。インタフェースの共分散も同様に機能するはずです。 – CodesInChaos

答えて

2

あなたの実装が、その後Enumerable.OfType<>と同じ結果が得られますかどうか迷っているならば、それはなります。

Enumerable.OfType<>は、その実装としてisを使用し、そしてthis answer示すように、isキーワードは同じ結果Type.IsAssignableFrom()を与えます。あなたが必要とする情報の

他の作品はIsInstanceOfType()IsAssignableFromを使用して実装されていることである。

public virtual bool IsInstanceOfType(Object o) 
{ 
    if (o == null) 
     return false; 

    // No need for transparent proxy casting check here 
    // because it never returns true for a non-rutnime type. 

    return IsAssignableFrom(o.GetType()); 
} 

以下のテストコードは、あなたの元のコードが実際に相続で動作しないことを示す

Demo.Base 
Demo.Derived 

を印刷します:

using System; 
using System.Collections.Generic; 
using System.Linq; 

namespace Demo 
{ 
    public class Base {} 
    public class Derived : Base {} 

    class Program 
    { 
     static void Main() 
     { 
      object[] array = {"String", new Base(), new Derived(), 12345}; 

      foreach (var item in OfType(array, typeof(Base))) 
       Console.WriteLine(item); 
     } 

     public static IEnumerable<T> OfType<T>(IEnumerable<T> enumerable, Type type) 
     { 
      return enumerable.Where(element => type.IsInstanceOfType(element)); 
     } 
    } 
} 

IsInstanceOfType()IsAssignableFromを使用して実装されているので、あなたはそのようなあなたのメソッドを書くことができます。

public static IEnumerable<T> OfType<T>(this IEnumerable<T> enumerable, Type type) 
{ 
    return enumerable.Where(element => type.IsAssignableFrom(element.GetType())); 
} 
+1

* close *は* same *を意味しますか? – CodesInChaos

+0

@CodesInChaos私は彼の2番目のコードサンプルを見ていました。はい、私はこの答えは冗長だと思います。 :)編集します。 –

+0

@SindriJóelsson 'Type.IsInstanceOfType()'は 'is'演算子と同じ結果を返し、' Enumerable。OfType <> 'は実装のために' is'を使用しますが、2つのメソッドで同じ結果が得られます。あなたが望んでいたものではありませんか? –

関連する問題