2013-04-06 5 views
31

私はこのようになりますよう、安全なキャストオブジェクトへの拡張メソッドを持っています。IsAssignableFrom、IsInstanceOfTypeとisキーワードは何ですか?

public static T SafeCastAs<T>(this object obj) { 
    if (obj == null) 
     return default(T); 

    // which one I should use? 

    // 1. IsAssignableFrom 
    if (typeof(T).IsAssignableFrom(obj.GetType())) 
     return (T)obj; 

    // 2. IsInstanceOfType 
    if (typeof(T).IsInstanceOfType(obj)) 
     return (T) obj; 

    // 3. is operator 
    if (obj is T) 
     return (T) obj; 

    return default(T); 
} 

あなたが見ることができるように、私は3の選択肢を持っているので、どちら私が使用するようにする必要がありますか?実際にIsAssignableFromIsInstanceOfTypeisの違いは何ですか?

答えて

42

あなたはあなたのための情報を持っているものを使用。

チェックしたいインスタンスと静的タイプがある場合は、isを使用してください。

静的タイプがない場合は、Typeオブジェクトがありますが、確認するインスタンスがある場合はIsInstanceOfTypeを使用してください。

インスタンスがなく、理論上のインスタンスTypeと別のTypeの互換性を確認したい場合は、IsAssignableFromを使用してください。

しかし、実際にはas operatorを再実装しているようです(ただし、null値のない値の型に対しては通常動作しますが、大きな制限はありません)。

9

演算子のバージョンを実践していると思いますが、値型と参照型で動作します。

私はのために行くだろう:種類と

public static T SafeCastAs<T>(this object obj) 
{ 
    return (obj is T) ? (T) obj : default(T); 
} 

IsAssignableFrom作品、およびインスタンスを持つis作品。あなたのケースでは同じ結果が得られますので、最も簡単なバージョンのIMHOを使用してください。

IsInstanceOfTypeについて:これはIsAssignableFromで実装されているため、違いはありません。

あなたはIsInstanceOfType()の定義を見て反射板を使用していることを証明することができます

public virtual bool IsInstanceOfType(object o) 
{ 
    if (o == null) 
    { 
     return false; 
    } 
    return this.IsAssignableFrom(o.GetType()); 
} 
3

カスタム "SafeCastAs"の代わりに "as"としてください。しかし、これはクラス(構造体ではない)に対してのみ機能します。したがって、このメソッドを構造体にも使用したい場合は、それを取得できます。

オペレータ "is"は、基本的にType.IsAssignableFromと同じものを提供します。したがって、 "is"だけを保持できるので、objを例外なくTにキャストできるかどうかをチェックします。したがって、あなたのメソッドの前の両方のチェックをカバーします。しかし、ユーザーが定義した変換のためにobjをTに割り当てることができるかどうかをチェックしないことに注意してください:explicitおよびimplicitキーワード。

+0

あなたの主張が正しいかどうかはわかりません。 'typeof(int)'は 'Type'型のオブジェクトを返します。最初の文は' Type'オブジェクトが明らかに 'int'ではないので失敗します。しかし、最初の文を 'a.GetType()。IsInstanceOfType(3)'に変更するとtrueを返します。私はここで 'IsInstanceOfType'を間違って使用していると思います。 –

+0

@JeffBridgman true、私の推測私はちょうどこれらの2つのメソッドの使用の違いを表示しようとしました。 '' ' Console.WriteLine(typeof(int?)。IsInstanceOfType(null)); Console.WriteLine(typeof(int?)。IsInstanceOfType(1)); Console.WriteLine(typeof(int?)。IsAssignableFrom(typeof(int))); '' ' この回答の一部を削除します。 – outcoldman

0

これらの関数と演算子は、異なる意味を持ちます。オブジェクトがある場合は、常に型を取得できます。あなたはあなたが持っているもので働くことはできませんが、あなたは何をする必要がありますか?

クラス階層を使って作業している場合、その違いは非常に明確です。例

 class ABase 
     { 

     } 

     class BSubclass : ABase 
     { 

     } 
    ABase aBaseObj = new ABase(); 
       BSubclass bSubclassObj = new BSubclass(); 

       ABase subObjInBaseRef = new BSubclass(); 

異なる操作を以下に

ルックは異なる結果をもたらします。

typeof(ABase).IsInstanceOfType(aBaseObj) = True 

typeof(ABase).IsInstanceOfType(bSubclassObj) = True 

typeof(ABase).IsInstanceOfType(bSubclassObj) = True 

typeof(BSubclass).IsInstanceOfType(aBaseObj) = False 

bSubclassObj is ABase = True 

aBaseObj is BSubclass = False 

subObjInBaseRef is BSubclass = True 

subObjInBaseRef is BSubclass = True 

typeof(ABase).IsAssignableFrom(typeof(BSubclass)) = True 

typeof(BSubclass).IsAssignableFrom(typeof(ABase))= False 

階層がない場合、すべてが同じであった可能性があります。 階層で作業する場合、IsAssignableFromは、となり、IsInstanceOfTypeは異なる結果をもたらします。

試してみる可能性のある組み合わせがさらにあります。たとえば、この例で既存のクラスと関係のないクラスCを導入することができます。

関連する問題