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
Object
是MyClass
的实例为FALSE)为TRUEtestClass
设置为Object
testClass
对象==
我相信这是正确的功能。。。最终,代码试图返回两个类中最超级的类(您也可以说是公共基类),如果它们不相关,则返回null。使用上面的例子(步骤1-5),说leftClass是rightClass的一个超类,这难道不是正确的吗。。。或者,反过来说,rightClass是leftClass的子类?
leftClass。IsInstanceOfType(right)
表示“右边是左边”<代码>右类。IsInstanceOfType(左)表示“左是右”
如果右是左,但左不是右,那么左必须是超类,右必须是子类。这相当于第一种情况,其中有注释“rightClass是leftClass的子类”。因此,看来这些评论的意图实际上是准确的 但是,我发现该方法存在一些问题。这些评论是你最不担心的
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());
}