Сравнение типов объектов C # - PullRequest
57 голосов
/ 02 апреля 2009

Как я могу сравнить типы двух объектов, объявленных как тип.

Я хочу знать, относятся ли два объекта к одному и тому же типу или из одного базового класса.

Любая помощь приветствуется.

, например

private bool AreSame(Type a, Type b) {

}

Ответы [ 4 ]

85 голосов
/ 02 апреля 2009

Скажите a и b - это два объекта. Если вы хотите увидеть, находятся ли a и b в одной иерархии наследования, используйте 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.
}

В противном случае вам придется напрямую пройти иерархию наследования.

31 голосов
/ 02 апреля 2009

Однако есть некоторая проблема с этой идеей, поскольку каждый объект (и, действительно, каждый тип) имеет общий базовый класс Object. Вам нужно определить, как далеко вы хотите пройти по цепочке наследования (являются ли они одинаковыми или имеют одного и того же непосредственного родителя, или один является непосредственным родителем другого, и т. Д.) И выполнить проверяет таким образом. IsAssignableFrom полезно для определения совместимости типов между собой, но не позволяет полностью установить, имеют ли они одного и того же родителя (если это то, что вам нужно).

Если ваши строгие критерии таковы, что функция должна возвращать true, если ...

  • Типы идентичны
  • Один тип является родителем (непосредственным или иным образом) другого
  • Оба типа имеют одного и того же непосредственного родителя

Вы можете использовать

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
}
13 голосов
/ 02 апреля 2009

Вы также можете использовать ключевое слово «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
2 голосов
/ 02 апреля 2009

Я опробовал следующее с иерархией, используя как интерфейсы, так и конкретные классы. Он проходит по цепочке базовых классов для одного из типов, пока не достигнет «объекта», при котором мы проверяем, присваивается ли текущий тип назначения типу источника. Мы также проверяем, имеют ли типы общий интерфейс. если они это сделают, то они '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());
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...