简体   繁体   English

通用类型转换器-TypeConverter或Convert.ChangeType

[英]Generic Type Converter - TypeConverter or Convert.ChangeType

I am trying to convert from a String aa generic type. 我正在尝试从String转换成通用类型。 The generic type will be an Int32, Int64, Boolean, Double and so on ... I tried two approaches: 通用类型将是Int32,Int64,Boolean,Double等。我尝试了两种方法:

public static Boolean TryParse<T>(String source, out T value) {

  TypeConverter converter = TypeDescriptor.GetConverter(typeof(T));

  try {

    value = (T)converter.ConvertFromString(source);
    return true;

  } catch {

    value = default(T);
    return false;

  }

}

public static Boolean TryChangeType<T>(Object source, out T value) {

  try {

    Type type = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T);

    value = (T)Convert.ChangeType(source, type);
    return true;

  } catch {

    value = default(T);
    return false;

  }

}

The second one is more generic as it accepts an Object. 第二个更通用,因为它接受一个对象。

I am also considering passing an IFormatProvider in TryChangeType that would be used in Convert.ChangeType to resolve Culture issues and so on. 我还考虑在TryChangeType中传递IFormatProvider,该IFormatProvider将在Convert.ChangeType中用于解决区域性问题,等等。

Do you consider the second approach better? 您认为第二种方法更好吗?

Any way I can improve my code? 有什么办法可以改善我的代码吗?

In the first example of yours you can get rid of the try catch block by calling CanConvertTo() and CanConvertFrom() beforehand. 在您的第一个示例中,您可以通过预先调用CanConvertTo()CanConvertFrom()摆脱try catch块。

public static bool TryParse<T>(string source, out T value)
{
    TypeConverter converter = TypeDescriptor.GetConverter(typeof (T));
    if (converter.CanConvertTo(typeof (T)) && converter.CanConvertFrom(typeof (string)))
    {
        value = (T)converter.ConvertFromString(source);
        return true;
    }
    else
    {
        value = default (T);
        return false;
    }
}

In the second example why not make it even more generic and pass in a generic type? 在第二个示例中,为什么不使其更通用并传递通用类型呢?

Convert only works if the type implements the interface IConvertible so you can check for that, on the other hand it stil doesn't ensure that the conversion will be possible. 仅当类型实现接口IConvertible时, Convert才起作用,因此您可以进行检查,另一方面,stil不能确保可以进行转换。

        public static bool TryChangeType<T, TR>(T input, out TR output) where T : IConvertible
    {
        bool result = false;
        try
        {
            Type type = Nullable.GetUnderlyingType(typeof(TR));
            output = (TR)Convert.ChangeType(input, type);
            result = true;
        }
        catch(Exception)
        {
            output = default(TR);
        }
        return result;
    }

It would be nice to only catch the exceptions you know of: 仅捕获您所知道的异常将是很好的:

            catch(InvalidCastException)
        {
            output = default(TR);
            //Conversion is not unsupported
        }
            catch(FormatException)
        {
            output = default(TR);
            //string input value was in incorrect format
        }
            catch(InvalidCastException)
        {
            output = default(TR);
            //Conversion is not unsupported
        }
            catch(OverflowException)
        {
            output = default(TR);
            //narrowing conversion between two numeric types results in loss of data
        }

This might not answer the question fully, but you were asking for possible improvements so I thought why not. 这可能无法完全回答问题,但是您正在寻求可能的改进,所以我想为什么不这样做。

The second one is applicable only for IConvertible types. 第二个仅适用于IConvertible类型。 If this is what you want, you might want to apply a constraint, too ( ChangeType will throw an exception for non-convertible types anyway): 如果这是您想要的,那么您可能也想应用一个约束(无论如何, ChangeType都会为不可转换类型抛出异常):

public static Boolean TryChangeType<T>(Object source, out T value)
    where T : IConvertible
{
    // ...
}

The first one is more general, TypeConverter is used when the .NET component model should be used. 第一个比较笼统,当应使用.NET组件模型时,将使用TypeConverter For example, in designers, type converters are used to convert the values from string in the property grid. 例如,在设计人员中,类型转换器用于从属性网格中的字符串转换值。 But you should add a small additional check here, too: 但是您也应该在此处添加一个小的附加检查:

if (!converter.CanConvertFrom(typeof(string)))
    return false;

Additionally, I would mention that you should use the ConvertFromInvariantString method if you do not want trouble with the different region settings (in case of floating point values, for example)... 另外,我要提到的是,如果您不希望对其他区域设置感到麻烦(例如,在浮点值的情况下),则应使用ConvertFromInvariantString方法...

In your first example TypeDescriptor.GetConverter(Type) can throw exceptions, so move that into the try block. 在第一个示例中, TypeDescriptor.GetConverter(Type)可以引发异常,因此将其移入try块。 Without trying them personally, out of your two approaches I like the second one. 如果没有亲自尝试,则从您的两种方法中我都喜欢第二种。

This post shows an example of testing for convertibility with no try/catch and claims performance benefits. 这篇文章展示了一个没有可尝试性/可移植性的可转换性测试示例,并声称具有性能优势。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM