给定一个Type和一个String,你可以尝试将String转换为该Type而不插入Type吗?

时间:2016-02-25 18:32:35

标签: c# parsing types casting

我有一个List<Type>代表来自自定义脚本语言的基于文本的命令的签名。我正在尝试确定如何将String[]解析为List<object>,其中对象类型与List<Type>相关联。基本上给出Type t我想尝试将String s投射到Type

到目前为止,我有这个

Type t = ...;
String s = ...;
if(Convert.ChangeType(s, t) != null)
{

}

在考虑Convert.ChangeType后,我怀疑是否正确。它只是简单地改变给定对象的类型,而不是“解析”它。看你不能简单地做(double)"ImAString"我会假设这个方法将用于在“直接”可转换的对象类型之间进行转换。

这有什么一般解决方案吗?或者是唯一的方法是在给定的switch上创建一个大Type并在每种情况下进行解析(很可能在将来缺少切换中的类型)?

编辑:此外,ChangeType的返回类型是对象。我假设如果我要做retObjectFromChange is double将是真的(假设我将类型更改为double)?

2 个答案:

答案 0 :(得分:2)

Convert.ChangeType()会尽可能地将字符串解析为数字,在非有效数字的字符串上抛出异常。

注意:如果您要在自己的自定义类型之间进行大量转换,则可能需要使用TypeConverter。 (TypeConverter在将两者转换为原始类型(如string时)时效果会更好。)

请参阅: Convert System.String generically to any complex type using "Convert.ChangeType()"

编辑: 是的,假设没有抛出异常,Convert.ChangeType("1.02", typeof(double)) is double应评估为true。

答案 1 :(得分:2)

这是我目前的实施。我发现Guid,DateTime,enums和nullables是我的优势。我输入逻辑来处理空字符串和空值。我对一些原语进行了具体处理,因为我发现TypeConverter比较慢,并且它们是我的一般情况。

    public object GetValue(string readerValue, Type conversionType)
    {
        // if the type is a string, just return the value with no conversion
        if (conversionType == typeof(string) || conversionType == typeof(object))
        {
            return readerValue;
        }

        // if the field has a value try to cast it
        if (!string.IsNullOrWhiteSpace(readerValue))
        {
            readerValue = readerValue.Trim();

            if (conversionType.IsEnum)
            {
                return Enum.Parse(conversionType, readerValue);
            }
            else
            {
                Type underlyingType = Nullable.GetUnderlyingType(conversionType) ?? conversionType;

                if (underlyingType == typeof(int))
                {
                    return int.Parse(readerValue);
                }
                else if (underlyingType == typeof(bool))
                {
                    return bool.Parse(readerValue);
                }
                else if (underlyingType == typeof(DateTime))
                {
                    return DateTime.Parse(readerValue);
                }
                else if (underlyingType == typeof(double))
                {
                    return double.Parse(readerValue);
                }
                else if (underlyingType == typeof(long))
                {
                    return long.Parse(readerValue);
                }
                else if (underlyingType == typeof(Guid))
                {
                    return Guid.Parse(readerValue);
                }
                else
                {
                    // GetConverter and ConvertFrom are both slow, so only use it in a fallback
                    TypeConverter converter = TypeDescriptor.GetConverter(underlyingType);
                    return converter.ConvertFrom(readerValue);
                }
            }
        }
        // return null for nullable generic primitives
        else if (conversionType.IsGenericType && conversionType.GetGenericTypeDefinition() == typeof(Nullable<>))
        {
            return null;
        }
        // return the default value for non nullable primitive types
        else if (conversionType.IsValueType)
        {
            return Activator.CreateInstance(conversionType);
        }
        // return null for reference types
        else
        {
            return null;
        }
    }