7

我决定检查一个函数中的类型,而不是重载一个函数 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返回一个动态获取的字符串,这个方法涉及到字符串比较。这对我来说听起来不是特别快。我需要比较器在技术上尽可能快,因为它将用于大量数据集合。

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

4

2 回答 2

8

好吧,你手里拿着它。利用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;
        }

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

我希望这有帮助。

于 2013-07-21T16:22:45.083 回答
3

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

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

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

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

于 2013-07-21T16:32:47.113 回答