【问题标题】:C# Object Type ComparisonC# 对象类型比较
【发布时间】:2010-10-17 00:44:13
【问题描述】:

如何比较声明为类型的两个对象的类型。

我想知道两个对象是否属于同一类型或来自同一基类。

感谢任何帮助。

例如

private bool AreSame(Type a, Type b) {

}

【问题讨论】:

    标签: c# types


    【解决方案1】:

    如果您希望两个对象实例属于某种类型,您也可以使用“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
    

    【讨论】:

    • 我不知道它们可以是什么类型,只需要知道它们是否相同或来自同一个基类。
    • 这仅适用于类型的实例,不适用于 Type 类型的类型。
    【解决方案2】:

    假设ab 是两个对象。如果要查看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.
    }
    

    否则,您将不得不直接遍历继承层次结构。

    【讨论】:

    • +1 我不知道 IsAssignableFrom 这个方便的函数,我必须记住这一点。
    • 反射层次中有很多有用的东西!浏览成员列表很有趣——很有可能你会找到你需要的东西。不过,请阅读文档。例如,如果 t 是泛型类型参数且 u 是约束,则 IsAssignableFrom 将返回 true。
    • 仅供参考,如果两个类具有相同的基类,则不会返回 true。
    • @AdamRobinson:我不确定这是一个有用的区别。每个引用类型都来自 System.Object,因此它们全部具有相同的基类。
    • @John:看我的回答。显然,一切都源于对象。然而,张贴者表示,知道这些类是否具有相同的基类(我说你必须决定你要走多远)对他来说是有价值的,因此我做出了回应。跨度>
    【解决方案3】:

    不过,这个想法有一点问题,因为每个对象(实际上,每个类型)都有一个公共基类 Object。您需要定义的是您想要在继承链上走多远(无论它们是相同的还是具有相同的直接父级,或者一个是另一个的直接父级,等等)并做你的那样检查。 IsAssignableFrom 可用于确定类型是否相互兼容,但不能完全确定它们是否具有相同的父对象(如果这是您所追求的)。

    如果您的严格标准是函数应该返回 true if...

    • 类型相同
    • 一种类型是另一种类型的父级(直接或其他)
    • 这两种类型具有相同的直接父级

    你可以使用

    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
    }
    

    【讨论】:

    • 很好的示例和解释。 +1
    • 我希望有一种方法可以分享一个接受的答案。再次感谢。
    • @Adam:我想知道是否没有办法将我们的两种方法结合起来。您可以保留在 a 和 b 上采用 BaseType.GetType() 导致的类型列表,直到您 (1) 到达 System.Object (或一些更受限制的派生类型) [失败] 或 (2) 匹配 [通过]。
    • 哦,当然。这就是为什么我说你必须决定你想在堆栈上走多远......你也可以遇到像 MarshalByRefObject 这样的一般系统类型,但是,你绝对可以在堆栈上走得更远。
    • 在 Type 变量上做一个 while() 循环可能更容易,获取两个变量的基本类型(我不认为不应该两者都做)并限制它不知何故,要么不允许系统程序集中的任何基本类型,要么允许许多“跃点”。
    【解决方案4】:

    我使用接口和具体类尝试了以下层次结构。 它遍历其中一种类型的基类链,直到到达“对象”,在该“对象”处,我们检查当前目标类型是否可分配给源类型。 我们还检查类型是否具有公共接口。如果他们这样做,那么他们'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());
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2023-03-11
      • 2014-06-13
      • 1970-01-01
      • 1970-01-01
      • 2021-12-31
      • 1970-01-01
      • 1970-01-01
      • 2012-09-14
      • 1970-01-01
      相关资源
      最近更新 更多