web-dev-qa-db-ja.com

C#オブジェクトタイプの比較

型として宣言された2つのオブジェクトの型を比較す​​るにはどうすればよいですか。

2つのオブジェクトが同じ型であるか、同じ基本クラスであるかを知りたい。

どんな助けも大歓迎です。

例えば.

private bool AreSame(Type a, Type b) {

}
58
B Z

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

特定の基本クラスがわかっている場合は、isキーワードを使用します。

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

それ以外の場合は、継承階層を直接歩く必要があります。

86
John Feminella

ただし、すべてのオブジェクト(そして実際、すべてのタイプ)には共通の基本クラスであるObjectがあるため、この考えには少し問題があります。定義する必要があるのは、継承の連鎖をどれだけ上に行くか(それらが同じであるか、同じ親を持っているか、一方が他方の親であるかなど)そのようにチェックします。 IsAssignableFromは、型が相互に互換性があるかどうかを判断するのに役立ちますが、同じ親を持つかどうかを完全に確立することはできません(それが目的の場合)。

次の場合に関数がtrueを返すことが厳密な基準である場合.

  • タイプは同一です
  • 1つのタイプは他のタイプの親(即時またはそれ以外)です。
  • 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
}
31
Adam Robinson

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
13
James

インターフェースと具象クラスの両方を使用した階層で次のことを試しました。現在の宛先タイプがソースタイプに割り当て可能かどうかをチェックする「オブジェクト」に到達するまで、いずれかのタイプのベースクラスチェーンを上に向かって歩きます。また、型に共通のインターフェイスがあるかどうかも確認します。もしそうなら、彼らは「同じ」

お役に立てれば。

 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());
    }
}
2
Abhijeet Patel