【问题标题】:Check if String can be converted to a given type in C# [duplicate]检查String是否可以在C#中转换为给定类型[重复]
【发布时间】:2011-12-28 16:28:08
【问题描述】:

我必须验证用户输入数据并确保字符串值可转换为运行时指定的类型。我不一定需要进行实际转换,只需测试以确保输入值有效。我还没有找到可以执行此类评估的内置类或方法,但如果我缺少一个,请告诉我。如果有任何版本特定的解决方案可用,我正在使用 C#4.0。

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

我目前正在权衡 2 个解决方案,但都不是完美的,所以我希望有第 3 个选项(或者我错过的框架内置的东西)。我非常倾向于解决方案 #2,因为在解决方案 #1 中使用 try-catch 似乎是错误的。

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

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:检查某些内容是否可以转换到实际转换的工作量通常很小。
  • @Joe 我有一种感觉,但由于 TryParse 方法非常快,没有明显的异常,我想知道是否有一种内置方法可以在转换之前先检查。

标签: c# type-conversion


【解决方案1】:

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

parapura rajkumar 使用 TypeConverter 类走在正确的轨道上,但我试图避免对非异常事件的 CanConvertFrom 方法进行所需的异常处理。

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

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

【讨论】:

    【解决方案2】:

    考虑使用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");
            }
        }
    

    【讨论】:

    • 我不确定我是否遵循这解决了检查类型是否有效的原始问题。如果我将无效值传递给转换器(例如,int 的“14.1”),它会抛出 FormatException。我的第一个解决方案已经这样做了,所以我不确定为什么这是更可取的。
    • 这更可取,因为该方法是通用的,不需要为您添加的每个新类型添加新的 if 块
    【解决方案3】:

    我更喜欢TryParse-方式,因为异常很昂贵(性能)。

    【讨论】:

    • 最后,我接受了这个建议,因为 TypeConverter 答案需要异常处理,我想避免这种情况。
    猜你喜欢
    • 1970-01-01
    • 2013-07-14
    • 1970-01-01
    • 2013-05-29
    • 2012-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-08
    相关资源
    最近更新 更多