TypeConverter vs. Convert vs. TargetType.Parse

本文关键字:vs Parse TargetType Convert TypeConverter | 更新日期: 2023-09-27 18:04:56

据我所知,在。net中至少有3种转换数据类型的方法:


使用System.ComponentModel.TypeConverter

var conv = System.ComponentModel.TypeDescriptor.GetConverter(typeof(int));
var i1 = (int)conv.ConvertFrom("123");
使用System.Convert.ChangeType ()

:

var i2 = (int) Convert.ChangeType("123", typeof (int));

使用目标类型的Parse/TryParse方法:

var i3 = int.Parse("123"); // or TryParse



是否有任何指导方针或经验法则何时使用哪个方法在。net基本数据类型之间转换(特别是从字符串到其他数据类型)?

TypeConverter vs. Convert vs. TargetType.Parse

我将在6年后在这里发布,因为我认为这是一个很好的问题,我对现有的答案不满意。

静态Parse/TryParse方法只能在您想要从字符串转换为具有这些方法的类型时使用。(当您预计转换可能失败时,请使用TryParse)。

System.Convert的意义在于,正如其文档所说,将从基本数据类型转换为另一种基本数据类型。请注意,使用Convert,您还可以使用一些方法来获取Object并自行确定如何转换它。

对于System.ComponentModel.TypeConverter,作为"类型转换器"堆栈溢出标记的文档,它们主要用于将转换为字符串,当您希望提供类实例的文本表示以供设计器序列化或用于在属性网格中显示

转换

Convert类使用目标类型中实现的IConvertible方法。

不幸的是,实现IConvertible意味着编写大量的样板代码和转换。如果目标类型是struct,则ChangeType会导致装箱。

TypeConverterAttribute

TypeDescriptor。GetConverter使用TypeConverterAttribute, IMHO提供了一个更好的API来转换类型,也提供了一种更优雅的方式来转换类型。但是,由于方法不是泛型的,它遭受了与Convert类相同的性能问题。

解析/TryParse

使用T.Parse/T.TryParse方法是从字符串创建对象的事实上的方式,因为它不涉及不必要的装箱。它们通常还具有重载,可以更好地控制如何解析字符串。

TryParse方法允许您处理想要解析的字符串是从用户输入或其他不能保证正确格式化字符串的方式获得的情况,而不会抛出异常。


所以你应该调用类型的Parse/TryParse方法当你可以和回退到其他方法只有当你不知道在编译时的目标类型,即当你只有一个类型对象,代表你的目标类型。

你也可以看看我的一个叫做ValueString的小库,它可以找到一个类型最合适的解析方法,并用它来解析字符串。

根据我的个人喜好和编码标准,我在以下两者之间进行选择:

  1. Convert。当我绝对确定这些值将是我所期望的值时,我使用这种方法。

    int i = Convert.ToInt32("123");
    
  2. TryParse。我在处理用户输入时使用这个。这样做的好处是可以在解析时使用本地化的格式。

    int i = 0;
    bool parsed = Int32.TryParse("123", out i);
    

也可以使用TryParseExact,其中可以解析特定的模式。它在某些情况下是有用的。

刚刚发现一个TypeConvert.ConvertFrom(object)抛出异常的情况。如果要将整数0/1转换为布尔值。使用TypeConvert.ConvertFrom(1)(0)会得到异常。在这种情况下,Convert.ChangeType(1, System.Boolean)工作。

一般来说,您应该完全避免使用Convert类。使用它是有原因的(例如,你不知道源类型),但是如果你已经知道源类型是string,那么Parse(或者更正确地说,TryParse)总是正确的方法。

至于类型转换器,当框架(如WPF)使用反射来确定类型转换器的正确类型时,通常会使用它们。

您忘记了另一种转换方式,那就是直接强制转换。以以下代码为例

object i = 1;
int myInt = (int)i;

这是一个有点人为的例子,但我已经知道i是一个int,只是它被装箱成object。在这种情况下,我不需要转换i,我只需要直接将其转换为我知道它已经是的类型。

当我确定它是一个数字时,我几乎总是使用int/double/etc.Parse()方法。在任何有疑问的情况下,我使用. tryparse()方法作为包括解析和检查在内的一体化解决方案。我有一种感觉,检查和解析结合起来比单独执行要稍微高一些。

TypeConverter可能只在编译时不知道类型时才有用。

又一个迟到的回答。我有一个应用程序,我使用了一些代码,看起来像这样:

var finalValue = Convert.ChangeType(sourceValue, targetProperty.PropertyType);

sourceValue将是我想要的string表示,通常是wrapper class下的primitive。这种方法适用于常规数据类型。甚至是整个班级。然而,有一天我愚蠢地决定改变一个属性的数据类型,这是一个double到一个可空的double?猜猜看?繁荣!

从字符串强制转换为可空的双精度

这是一个完美的场景,您应该像这样使用TypeConverter 类:

void Main()
{
    var ss = new[] {"2.01", "3.99", ""};
    var conv = TypeDescriptor.GetConverter(typeof(A).GetProperties().First().PropertyType);
    Console.WriteLine(string.Join(",", ss.Select(s => conv.ConvertFrom(s))));
}
class A {
    public double? b {get; set;}
}
//2.01,3.99,