2009-04-02 26 views
56

型として宣言された2つのオブジェクトの型を比較す​​る方法を教えてください。C#オブジェクト型の比較

2つのオブジェクトが同じタイプか同じ基本クラスであるかどうかを知りたいです。

何か助けていただければ幸いです。

private bool AreSame(Type a, Type b) { 

} 

答えて

84

セイabは、2つのオブジェクトです。あなたはabは、同じ継承階層にあるかどうかを確認したい場合は、Type.IsAssignableFrom使用:あなたは一方が他方の基底クラスであるかどうかを確認したい場合は

var t = a.GetType(); 
var u = b.GetType(); 

if (t.IsAssignableFrom(u) || u.IsAssignableFrom(t)) { 
    // x.IsAssignableFrom(y) returns true if: 
    // (1) x and y are the same type 
    // (2) x and y are in the same inheritance hierarchy 
    // (3) y is implemented by x 
    // (4) y is a generic type parameter and one of its constraints is x 
} 

を、その後、Type.IsSubclassOfを試してみてください。あなたが直接継承階層を歩かなければならないでしょう、そうでない場合

if (a is T && b is T) { 
    // Objects are both of type T. 
} 

:あなたは、特定の基本クラスを知っている場合

は、その後、ちょうどisキーワードを使用します。

+0

+1私はその便利な機能IsAssignableFromを知らなかった、私はそれを念頭に置いておく必要があります。 – James

+0

Reflection階層にはかなりのものがあります。メンバーリストを閲覧するのは興味深いことです。チャンスはあなたが必要とするものを見つけることができます。しかし、ドキュメントを読んでください。たとえば、IsAssignableFromは、tがジェネリック型のparamであり、uが制約の場合にtrueを返します。 –

+0

しかし、2つのクラスが同じ基本クラスを持つ場合、これはtrueを返しません。 –

13

また、あなたは2つのオブジェクトインスタンスが特定の型であることを期待する場合は、キーワード「IS」を使用することができます。これは、サブクラスを親クラスと比較したり、インタフェースなどを実装するクラスとの比較にも使用できます。しかし、これはType型の型に対しては機能しません。

if (objA Is string && objB Is string) 
// they are the same. 

public class a {} 

public class b : a {} 

b objb = new b(); 

if (objb Is a) 
// they are of the same via inheritance 
+0

私は彼らが同じタイプか同じベースクラスかを知る必要があるのか​​分かりません。 –

+1

これは型のインスタンスでのみ機能し、型の型では機能しません。 –

31

しかし、すべてのオブジェクト(実際にはすべての型)に共通の基本クラスObjectがあるため、このアイディアには少し問題があります。あなたが定義する必要があるのは、あなたが行きたい継承のチェーンのどれくらいの距離(彼らが同じであるか、それとも同じ親を持っているのか、もう片方の親であるのかなど)その方法をチェックする。 IsAssignableFromは、型が互いに互換性があるかどうかを判断するのに便利ですが、それらが同じ親を持っているかどうかを完全に確認することはできません。他のの

あなたの厳格な基準は機能が...

  • 型が同一である場合
  • 一つのタイプは、親(即時またはそれ以外)でtrueを返す必要があることである場合
  • 2タイプが同じ直接の親

を持っているあなたは

private bool AreSame(Type a, Type b) 
{ 
    if(a == b) return true; // Either both are null or they are the same type 

    if(a == null || b == null) return false; 

    if(a.IsSubclassOf(b) || b.IsSubclassOf(a)) return true; // One inherits from the other 

    return a.BaseType == b.BaseType; // They have the same immediate parent 
} 
を使用することができます
+0

素晴らしいサンプルと説明。 +1 –

+0

私は受け入れられた答えを共有する方法があることを望みました。再びThx。 –

+0

@アダム:両方のアプローチを組み合わせる方法がないのだろうか? (1)System.Object(またはいくつかのより限定された派生型)[fail]に到達するか、または(2)一致するまでBaseType.GetType()をaとbの両方に使用した結果のTypesのリストを保持することができます[パス]。 –

2

私は、インターフェイスとコンクリートクラスの両方を使って階層を使って試しました。 現在の宛先タイプがソースタイプに割り当て可能かどうかをチェックする「オブジェクト」に達するまで、いずれかのタイプの基本クラスチェーンを処理します。 また、タイプに共通のインタフェースがあるかどうかを確認します。もし彼らがそうすれば、彼らは 'AreSame'

希望がこれを助けます。

public interface IUser 
{ 
    int ID { get; set; } 
    string Name { get; set; } 
} 

public class NetworkUser : IUser 
{ 
    public int ID 
    { 
     get; 
     set; 
    } 

    public string Name 
    { 
     get; 
     set; 
    } 
} 

public class Associate : NetworkUser,IUser 
{ 
    #region IUser Members 

    public int ID 
    { 
     get; 
     set; 
    } 

    public string Name 
    { 
     get; 
     set; 
    } 

    #endregion 
} 

public class Manager : NetworkUser,IUser 
{ 
    #region IUser Members 

    public int ID 
    { 
     get; 
     set; 
    } 

    public string Name 
    { 
     get; 
     set; 
    } 

    #endregion 
} 


public class Program 
{ 

    public static bool AreSame(Type sourceType, Type destinationType) 
    { 
     if (sourceType == null || destinationType == null) 
     { 
      return false; 
     } 

     if (sourceType == destinationType) 
     { 
      return true; 
     } 

     //walk up the inheritance chain till we reach 'object' at which point check if 
    //the current destination type is assignable from the source type  
    Type tempDestinationType = destinationType; 
     while (tempDestinationType.BaseType != typeof(object)) 
     { 
      tempDestinationType = tempDestinationType.BaseType; 
     } 
     if(tempDestinationType.IsAssignableFrom(sourceType)) 
     { 
      return true; 
     } 

     var query = from d in destinationType.GetInterfaces() join s in sourceType.GetInterfaces() 
        on d.Name equals s.Name 
        select s; 
     //if the results of the query are not empty then we have a common interface , so return true 
    if (query != Enumerable.Empty<Type>()) 
     { 
      return true; 
     } 
     return false;    
    } 

    public static void Main(string[] args) 
    { 

     AreSame(new Manager().GetType(), new Associate().GetType()); 
    } 
} 
+0

thxです。 +1 –