2013-07-21 133 views
6

而不是重载一个函数100次或为不同的类型创建100个不同的比较器我决定检查一个函数内的类型。什么是检查类型的最快方法?

例如,我使用默认比较器来比较2个对象中的一组类型(基元和字符串)的值。它包含以下代码:

public class DefComparer : IComparer<object> { 
    public int Compare(object a, object b) { 
     .... // a = a.GetType().GetField(field).GetValue(a); - not important for the question but I'm just showing that a&b below are different references 
     switch (a.GetType().Name) { 
      case "Byte": 
       if ((byte)a == (byte)b) return 0; 
       else if ((byte)a > (byte)b) return 1; 
       else return -1; 
      case "UInt16": 
       if ((ushort)a == (ushort)b) return 0; 
       else if ((ushort)a > (ushort)b) return 1; 
       else return -1; 
      case "SByte": 
       if ((sbyte)a == (sbyte)b) return 0; 
       else if ((sbyte)a > (sbyte)b) return 1; 
       else return -1; 
      case "Int16": 
       ... 

这里我使用的是switch声明被认为是比if/else语句链更快。但a.GetType().Name返回一个动态获取的字符串,此方法涉及字符串比较。这听起来并不特别快。我需要比较器的速度尽可能快,因为它将用于大量的数据集合。

问:有没有更快的方法来检查对象的类型(不涉及字符串比较)?什么是最快的方法?

+1

您正在寻找'Comparer.Default'。 – SLaks

+0

或者调用((IComparable)a).CompareTo(b) – usr

+0

不,我不是在寻找'Comparer.Default'。我编辑了我的帖子,使其更加清晰。我的问题是关于检查类型的快速方法。 – brandon

回答

6

那么你有它在你的手中。使用TypeCode

 int a = 10; 
     Type t = a.GetType(); 

     switch (Type.GetTypeCode(t)) 
     { 
      case TypeCode.Boolean: 
       break; 
      case TypeCode.Byte: 
       break; 
      case TypeCode.Char: 
       break; 
      case TypeCode.DBNull: 
       break; 
      case TypeCode.DateTime: 
       break; 
      case TypeCode.Decimal: 
       break; 
      case TypeCode.Double: 
       break; 
      case TypeCode.Empty: 
       break; 
      case TypeCode.Int16: 
       break; 
      case TypeCode.Int32: 
       break; 
      case TypeCode.Int64: 
       break; 
      case TypeCode.Object: 
       break; 
      case TypeCode.SByte: 
       break; 
      case TypeCode.Single: 
       break; 
      case TypeCode.String: 
       break; 
      case TypeCode.UInt16: 
       break; 
      case TypeCode.UInt32: 
       break; 
      case TypeCode.UInt64: 
       break; 
      default: 
       break; 
     } 

这支持所有原语。自定义对象在TypeCode.Object中写入else if语句。

我希望这会有所帮助。

+0

是的,测试表明你的方法更快。我不知道'TypeCode'枚举。 – brandon

+0

@brandon欢呼,现在你知道了。 –

+0

@brandon我建议你投到适当的类型,并将其存储在本地变量,然后比较性能而不是“拆箱”两次 –

3

从评论中,听起来好像你有一堆结构化数据,其中有不同类型的子对象。

如果集合很大,最快的方法是动态代码生成器(可能有表达式树)来创建一个方法,以强类型方式提取所有感兴趣的字段/属性,并执行强类型比较。

基本上,您使用反射来从集合成员类型动态获取字段/属性类型。然后建立MemberAccessExpression表达式,将其传递给Expression.Equal,并将所有结果传递给Expression.AndAlso。编译表达式将为您提供一个委托,它包含集合中包含的特定类型的两个对象。

启动时间将比您在问题中显示的代码慢两个数量级,但每个对象的成本会降低很多。你必须进行测试,看看盈亏平衡点在哪里 - 但可能在几千美元。

相关问题