我如何确定 Int32 实际上是可从 Int16 分配的

How do I determine Int32 is in fact assignable from Int16

我有几个 PropertyInfo 对象表示目标对象的属性。还有一组类似的 PropertyInfo 对象,表示源对象的属性。

如果名称和类型匹配,我的代码会将 属性 值从源分配给目标。但是有些类型是可分配的,但不是完全匹配的。其中一种情况是 Int16 类型的源 属性,但在目标端,同名的 属性 是 Int32 类型。我使用 targetProperty.Type.IsAssignableFrom(sourceProperty.Type).

所以换句话说,当我真的希望它给我一个 `true' 时,以下返回 false

typeof(Int32).IsAssignableFrom(typeof(Int16))

我已阅读其他主题,这些主题提示我 IsAssignableFrom 不是我需要的。在我开始编写长的 switch-case 代码之前,我正在检查是否有更简单的方法。

Int32 (int)Int16 (short) 是结构。结构不允许继承。因此 IsAssignableFrom 不起作用,因为 short 没有继承自 int。但是把一个short赋给一个int是没有问题的。

Int16Int32 的隐式转换是 C# 语言功能,而不是 CLR 或 .NET 的功能,因此从技术上讲它们不是运行时可分配的(尽管,公平地说, IsAssignableFrom 会告诉你 object 可以从任何值类型分配,即使你在技术上需要装箱转换来完成它)。

除了像这样发出一个大的喇叭开关语句之外,我知道没有开箱即用的方法可以做到这一点:

public static bool HasImplicitConversion( Type source, Type destination )
{
    var sourceCode = Type.GetTypeCode( source );
    var destinationCode = Type.GetTypeCode( destination );
    switch( sourceCode )
    {
        case TypeCode.SByte:
            switch( destinationCode )
            {
                case TypeCode.Int16:
                case TypeCode.Int32:
                case TypeCode.Int64:
                case TypeCode.Single:
                case TypeCode.Double:
                case TypeCode.Decimal:
                    return true;
            }
            return false;
        case TypeCode.Byte:
            switch( destinationCode )
            {
                case TypeCode.Int16:
                case TypeCode.UInt16:
                case TypeCode.Int32:
                case TypeCode.UInt32:
                case TypeCode.Int64:
                case TypeCode.UInt64:
                case TypeCode.Single:
                case TypeCode.Double:
                case TypeCode.Decimal:
                    return true;
            }
            return false;
        case TypeCode.Int16:
            switch( destinationCode )
            {
                case TypeCode.Int32:
                case TypeCode.Int64:
                case TypeCode.Single:
                case TypeCode.Double:
                case TypeCode.Decimal:
                    return true;
            }
            return false;
        case TypeCode.UInt16:
            switch( destinationCode )
            {
                case TypeCode.Int32:
                case TypeCode.UInt32:
                case TypeCode.Int64:
                case TypeCode.UInt64:
                case TypeCode.Single:
                case TypeCode.Double:
                case TypeCode.Decimal:
                    return true;
            }
            return false;
        case TypeCode.Int32:
            switch( destinationCode )
            {
                case TypeCode.Int64:
                case TypeCode.Single:
                case TypeCode.Double:
                case TypeCode.Decimal:
                    return true;
            }
            return false;
        case TypeCode.UInt32:
            switch( destinationCode )
            {
                case TypeCode.UInt32:
                case TypeCode.UInt64:
                case TypeCode.Single:
                case TypeCode.Double:
                case TypeCode.Decimal:
                    return true;
            }
            return false;
        case TypeCode.Int64:
        case TypeCode.UInt64:
            switch( destinationCode )
            {
                case TypeCode.Single:
                case TypeCode.Double:
                case TypeCode.Decimal:
                    return true;
            }
            return false;
        case TypeCode.Char:
            switch( destinationCode )
            {
                case TypeCode.UInt16:
                case TypeCode.Int32:
                case TypeCode.UInt32:
                case TypeCode.Int64:
                case TypeCode.UInt64:
                case TypeCode.Single:
                case TypeCode.Double:
                case TypeCode.Decimal:
                    return true;
            }
            return false;
        case TypeCode.Single:
            return ( destinationCode == TypeCode.Double );
    }
    return false;
}