TypeCode 与 typeof

TypeCode vs typeof

如果我需要一些特定类型的代码,我可以使用 typeof 例如:

private static bool IsNumericType(Type type)
{
    return type == typeof(int) || type == typeof(decimal); //etc
}

但我也可以使用枚举 TypeCode

private static bool IsNumeric(TypeCode objTypeCode)
{
    return objTypeCode == TypeCode.Int16 || objTypeCode == TypeCode.Int32 || objTypeCode == TypeCode.Int64; // etc ||
}

从架构和性能的角度来看,使用 TypeCodetypeof 有什么好处?在哪种情况下我应该使用两者之一?

仅供参考,从值中获取 type / typeCode 的代码:

var type = value.GetType();
var typeCode =  Convert.GetTypeCode(value);

PS:这些示例已大大简化。

PS 2:如果我传递值,我也可以使用 asis 等。但是在这种情况下,我不喜欢发送,因为该方法没有不需要知道值,只需要知道它的类型。

回答前的几点说明:

  1. typeof 采用类型(不是实例)
  2. IConvertible.GetTypeCode 需要一个实现 IConvertible 接口的实例

因此它们是不同的。所以你需要问自己的问题是你想要一个实例的类型还是一个类型。


This is from Microsoft Docs:

Call the GetTypeCode method on classes that implement the IConvertible interface to obtain the type code for an instance of that class.
Otherwise, call an object's GetType method to obtain its Type object, then call the Type object's GetTypeCode method to obtain the object's type code.

因此,如果一个类型没有实现IConvertible接口,那么你需要进行2次调用:GetType然后调用GetTypeCode。我还从 .NET 源代码中提取了 GetTypeCode:

的代码
    public static TypeCode GetTypeCode(Type type)
    {
        if (type == null)
            return TypeCode.Empty;
        return type.GetTypeCodeImpl();
    }
    
    protected virtual TypeCode GetTypeCodeImpl()
    {
        // System.RuntimeType overrides GetTypeCodeInternal
        // so we can assume that this is not a runtime type
    
        // this is true for EnumBuilder but not the other System.Type subclasses in BCL
        if (this != UnderlyingSystemType && UnderlyingSystemType != null)
            return Type.GetTypeCode(UnderlyingSystemType);
        
        return TypeCode.Object;
    }

如您所见,那里发生了很多事情。现在没有基准测试很难说,但我很确定,因为 typeof 是编译时间,而且它是 C# 原生的,团队已经投入工作以使其高效。 typeof 的事实是:

  1. C# 原生
  2. 编译时决定
  3. 不依赖于接口
  4. 在某些情况下不是2次调用
  5. 更直接

我会选择 typeof

我一直记得这条规则:

首先让它发挥作用。然后,只有当你需要让它工作得更快时,才改变它。

TypeCode 在您遵循多个可能的路径时效果最佳,并且大部分或所有逻辑都可以通过单独检查代码来完成,因为 switch 这样做会非常有效,大体上很清楚。

在其他情况下,Object 分支内部的逻辑可能与外部的逻辑一样多,因为这是大多数类型的代码,在这种情况下,首先检查代码往往没有用除非也许它服务好的案例也是特别经常出现的案例。

您的 IsNumeric 示例是 TypeCode 何时运行良好的一个很好的示例,就像您将其重写为一个开关,您通过一个虚拟调用来获取代码和一个此类开关来应答编译成相对有效的跳转,而不是在不同可能类型的多重比较上分支。

请注意,枚举类型与其基础数字类型具有相同的代码。这算作免费涵盖这些案例,还是您必须单独防范的案例,取决于您出于何种目的如何考虑这些类型。