在C#中检查字符串是否可以转换为给定类型

12

我需要验证用户输入数据并确保字符串值可以在运行时转换为指定类型。我不一定需要执行实际的转换,只需测试以确保输入值有效。我没有找到内置的类或方法来执行这种类型的评估,但如果我漏掉了一个,请告诉我。我使用C#4.0工作,如果有特定于版本的解决方案可用。

该方法只需处理“标准”类型(内置值数据类型加上String)。我需要评估的唯一自定义类型是库中定义的特定枚举类型。

我目前有两个解决方案,但都不完美,所以我希望有第三个选项(或者是我错过的框架内置功能)。我倾向于解决方案#2,因为在解决方案#1中使用try-catch似乎不太合适。

解决方案1:使用try/catch的Convert.ChangeType()

public Boolean CheckType(String value, Type type)
{
    try
    {
        var obj = Convert.ChangeType(value, type);
        return true;
    }
    catch(InvalidCastException)
    {
        return false;
    }
    catch(FormatException)
    {
        return false;
    }
    catch(OverflowException)
    {
        return false;
    }
    catch(ArgumentNullException)
    {
        return false;
    }
}

解决方案2,使用类型检查和TryParse的if/else链。

public Boolean CheckType(String value, Type type)
{
    if (type == typeof(String))
    {
        return true;
    }
    else if (type == typeof(Boolean))
    {
        Boolean b;
        return Boolean.TryParse(value, out b); 
    }
    else if (type == typeof(Int32))
    {
        Int32 i;
        return Int32.TryParse(value, out i); 
    }
    else if (type == typeof(Int64))
    {
        Int64 l;
        return Int64.TryParse(value, out l); 
    }
    // similar code to check all other types 
    // (Int16, UInt32, UInt64, UInt16, Byte, SByte, Single, Double, Decimal,
    //  Enum, Char, DateTime)
    .
    .
    .
    .
    .
    else
        throw new ArgumentException("Invalid type evaluation");

}

如果输入数据严重混乱或损坏,这个方法可能在短时间内被调用几百甚至一千次,因此我担心重复的if/else检查会影响性能(我并不一定要优化,我只想确保我考虑了其他选项)。

我对这两种解决方案的另一个问题是,它们实际上都将字符串值转换为预期类型的新值,在这两种情况下,我都吞掉了结果。


@JeremyMcGee,我看到了你提供的链接,但由于我并不想实际转换该值,只是想测试它是否可以转换,所以我认为我的问题并不一定是重复的。 - psubsee2003
@psubsee2003:检查某个东西是否可以转换的工作量通常非常小,实际转换它的工作量也很小。 - Joe
@Joe我有一种感觉是这样的,但由于TryParse方法如此快速而没有明显的异常,所以我想知道是否有一种内置的方法可以在转换之前先进行检查。 - psubsee2003
3个回答

21

我在最近的另一个问题中找到了比我最初的想法更好的解决方案。

parapura rajkumar使用TypeConverter类是正确的,但对于非异常事件的CanConvertFrom方法所需的异常处理正是我试图避免的。

TypeConverter.IsValid方法解决了我的问题,尽管它并不理想,因为IsValid方法只是CanConvertFrom方法和所需的异常处理的包装器。

private Boolean CanCovert(String value, Type type)
{
    TypeConverter converter = TypeDescriptor.GetConverter(type);
    return converter.IsValid(value);
}

17
考虑使用TypeConverter和泛型方法。这样可以避免大量的if语句。请根据MSDN文档添加自己的错误处理。
 class Program
    {
        static T convert<T>(string s)
        {
            var typeConverter = TypeDescriptor.GetConverter(typeof(T));
            if (typeConverter != null && typeConverter.CanConvertFrom(typeof(string)))
            {
                return (T) typeConverter.ConvertFrom(s);
            }

            return default(T);
        }

        static void Main(string[] args)
        {
            int x = convert<int>( "45");
        }
    }

我不确定这个解决方案如何解决检查类型是否有效的原始问题。如果我将无效值传递给转换器(例如,将“14.1”传递给int),它会抛出FormatException异常。我的第一个解决方案已经做到了这一点,所以我不确定为什么这更可取。 - psubsee2003
4
这种方法更可取,因为它是通用的,并且不需要为每种新类型添加一个新的 if 块 - parapura rajkumar

5
我更倾向于使用 "TryParse" 的方法,因为异常会影响性能。

最终,我选择了这个推荐,因为 TypeConverter 的答案需要异常处理,而我想避免这种情况。 - psubsee2003

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接