Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 比较对象并确定公共类型_C#_.net_Inheritance_Types - Fatal编程技术网

C# 比较对象并确定公共类型

C# 比较对象并确定公共类型,c#,.net,inheritance,types,C#,.net,Inheritance,Types,简短版本:代码中的注释是否正确?我认为它们是不正确的,应该颠倒过来 public Type GetTestClass(Object left, Object right) { if (left == null || right == null) return null; Type leftClass = left.GetType(); Type rightClass = right.GetType(); Type testClass; if (leftC

简短版本:代码中的注释是否正确?我认为它们是不正确的,应该颠倒过来

public Type GetTestClass(Object left, Object right)
{
    if (left == null || right == null) return null;

    Type leftClass = left.GetType();
    Type rightClass = right.GetType();
    Type testClass;
    if (leftClass.IsInstanceOfType(right))
    {
        testClass = leftClass;
        if (!rightClass.IsInstanceOfType(left))
        {
            // rightClass is a subclass of leftClass
            testClass = rightClass;
        }
    }
    else if (rightClass.IsInstanceOfType(left))
    {
        testClass = rightClass;
        if (!leftClass.IsInstanceOfType(right))
        {
            // leftClass is a subclass of rightClass
            testClass = leftClass;
        }
    }
    else
    {
        // The two classes are not related.
        testClass = null;
    }

return testClass;
}
我在正在编写的代码库中遇到了这段代码,我认为这些注释是不正确的。我认为注释
//rightClass是leftClass的子类
//leftClass是rightClass的子类
是不正确的。例如,如果
leftClass
类型为
Object
,而
rightClass
类型为
MyClass
(从Object继承),那么这就是我认为代码的工作方式

  • Object
    MyClass
    为FALSE的实例
  • MyClass
    对象的实例
  • testClass
    设置为
    MyClass
  • NOT(
    Object
    MyClass
    的实例为FALSE)为TRUE
  • testClass
    设置为
    Object
  • 返回的
    testClass
    对象==

  • 我相信这是正确的功能。。。最终,代码试图返回两个类中最超级的类(您也可以说是公共基类),如果它们不相关,则返回null。使用上面的例子(步骤1-5),说leftClass是rightClass的一个超类,这难道不是正确的吗。。。或者,反过来说,rightClass是leftClass的子类?

    leftClass。IsInstanceOfType(right)
    表示“右边是左边”<代码>右类。IsInstanceOfType(左)
    表示“左是右”


    如果右是左,但左不是右,那么左必须是超类,右必须是子类。这相当于第一种情况,其中有注释“rightClass是leftClass的子类”。因此,看来这些评论的意图实际上是准确的

    但是,我发现该方法存在一些问题。这些评论是你最不担心的

  • 如果任一参数为null,它将抛出
    NullReferenceException

  • 它会对
    GetType()
    进行不必要的调用,因为
    的实际源代码是instanceoftype
    如下所示:

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

    您应该使用@ P.S.W.G.的建议并使用从中进行赋值,并且可能考虑重构签名比较两种类型而不是两个对象。

  • 任何两个具体类型都至少有一个公共基类型
    System.Object
    。此处返回null是不可接受的结果

  • 它不处理一种类型不是从另一种类型线性派生的情况,但两者都有一个比
    System.Object
    派生得更多的公共基类。比如说,

    public class Base { }
    
    public class A : Base { }
    
    public class B : Base { }
    
    您的方法会说
    A
    B
    是不相关的,并返回null,其中正确的“公共基”是
    base

  • 我会看看在上提供的实现,它仍然不完美,但比您发布的更好

    更新:工作代码 我决定不吝啬,我在下面发布了我用于此目的的方法。祝你好运

        /// <summary> Finds the most derived common base class of all the provided types, or System.Object if there is no common base class  </summary>
        public static Type CommonBaseClass(params Type[] types)
        {
            if(ReferenceEquals(types,null)) return typeof(object);
            types = types.Where(x => !ReferenceEquals(x,null)).Distinct().ToArray();
            switch (types.Length)
            {
                case 0: return typeof(object);
                case 1: return types[0].IsInterface ? typeof(object): types[0];
                default:
                    IEnumerable<IEnumerable<Type>> hierarchies = types.Select(ClassHierarchy).OrderBy(x => x.Count());
                    Queue<Type> smallest = new Queue<Type>(hierarchies.First().Reverse());
                    hierarchies = hierarchies.Skip(1);
                    do
                    {
                        int maxPossible = smallest.Count;
                        hierarchies = hierarchies.Select(each => each.Take(maxPossible));
                        Type candidate = smallest.Dequeue();
                        if (hierarchies.All(each => each.Last() == candidate))
                            return candidate;
                    } while (smallest.Count > 1);
                    return typeof(object);
            }
        }
    
    
        ///<summary>Gets the class hierarchy of the provided type, in order of derivation, e.g. : (System.Object,CustomBaseType,CustomConcreteType,...), or the singleton of System.Object type if the provided type is an interface or null </summary>
        public static IEnumerable<Type> ClassHierarchy(this Type type)
        {
            if (type == null || type.IsInterface) type = typeof(object);
            var stack = new Stack<Type>();
            do
            {
                stack.Push(type);
                type = type.BaseType;
            } while (type != null);
            return stack;
    
        }
    
    ///查找所有提供的类型中最派生的公共基类,如果没有公共基类,则查找System.Object
    公共静态类型CommonBaseClass(参数类型[]类型)
    {
    if(ReferenceEquals(types,null))返回typeof(object);
    types=types.Where(x=>!ReferenceEquals(x,null)).Distinct().ToArray();
    开关(类型.长度)
    {
    案例0:返回类型(对象);
    案例1:返回类型[0]。IsInterface?typeof(对象):类型[0];
    违约:
    IEnumerable hierarchys=types.Select(ClassHierarchy.OrderBy(x=>x.Count());
    队列最小=新队列(hierarchies.First().Reverse());
    层次结构=层次结构。跳过(1);
    做
    {
    int maxPopuble=最小的.Count;
    Hierarcies=层次结构。选择(each=>each.Take(maxPopuble));
    类型候选者=最小的.Dequeue();
    if(hierarchies.All(each=>each.Last()==candidate))
    返回候选人;
    }而(最小计数>1);
    返回类型(对象);
    }
    }
    ///按派生顺序获取所提供类型的类层次结构,例如:(System.Object、CustomBaseType、CustomConcreteType,…)或System.Object类型的单例(如果所提供的类型是接口或null)
    公共静态IEnumerable类层次结构(此类型)
    {
    如果(type==null | | type.IsInterface)type=typeof(object);
    var stack=新堆栈();
    做
    {
    堆栈推送(类型);
    type=type.BaseType;
    }while(type!=null);
    返回栈;
    }
    
    编辑:更新以反映处理接口类型的更改。
    编辑:添加额外功能以支持两种以上类型

    首先:一个类型不能是另一个类型的实例(除非我们讨论的是
    type
    类型的实例),只有一个对象可以是一个类型的实例

    类型可以是彼此的子类型(使用
    IsSubType
    )。类型可以分配给另一个类型(使用
    IsAssignableFrom

    要查找常见类型,请尝试此示例。这将始终生成一个公共类型(对象):


    请告诉我你要在上面打一个[过时的(“请勿使用”)]!我添加了我遗漏的代码。代码中有比我在这里写的更多的东西。。。但这不适用于我的问题。到目前为止,我真的非常感谢下面的评论和代码。。。但是我想我的问题还没有得到回答,那就是:我对代码的理解正确吗?评论是错误的吗?@Steve,
    leftClas
    
        /// <summary>
        /// Returns the most common type of two types.
        /// If no common type can be found, null is returned.
        /// </summary>
        static public Type GetCommonBaseClass(Type a, Type b)
        {
            if ((a == null) || (b ==null))
                return null;
            if (a.IsInterface || b.IsInterface)
                return null;
            if (a.IsAssignableFrom(b))
                return a;
            while (true)
            {
                if (b.IsAssignableFrom(a))
                    return b;
                b = b.BaseType;
            }
        }
    
        /// <summary>
        /// Returns the most common type of one or more types.
        /// If no common type can be found, null is returned.
        /// </summary>
        static public Type GetCommonBaseClass(params Type[] types)
        {
            if ((types == null) || (types.Length == 0))
                return null;
            Type type = types[0];
            for (int i = 0; i < types.Length; i++)
                type = GetCommonBaseClass(type, types[i]);
            return type;
        }
    
    public Type GetTestClass(Object left, Object right)
    {
         return GetCommonBaseClass(left.GetType(), right.GetType());
    }