如何分析Nullable<T>的类型转换问题
这篇文章跟大家分析一下“如何分析Nullable<T>的类型转换问题”。内容详细易懂,对“如何分析Nullable<T>的类型转换问题”感兴趣的朋友可以跟着小编的思路慢慢深入来阅读一下,希望阅读后能够对大家有所帮助。下面跟着小编一起深入学习“如何分析Nullable<T>的类型转换问题”的知识吧。
下面讨论可空值类型(Nullable<T>)的转换,却确地说是如何将一种类型的值对象转换成相应的可空值。
一、四种典型的类型转换方式
对于类型转化,或者进一步地,对于像Int、Double、DateTime、String等这些原生类型之间的转化,我们具有四种典型的转换方式。如果类型之间不具有隐士转换关系存储,我们可以之间通过类型转换操作符进行显式转换,比如:
double doubleValue = 3.14159265; int intValue = (int)doubleValue;
第二种则是借助于Convert这个静态类型的ChangeType或者ToXxx方法(Xxx代表转换的目标类型),比如:
string literalValue = "123"; int intValue1 = Convert.ToInt32(literalValue); int intValue2 = (int)Convert.ChangeType(literalValue,typeof(int));
第三种方法为创建TypeConverter或者它的基于具体类型的若干子类,比如StringConverter、BooleanConverter、DateTimeConverter等。在使用的时候你需要先实例化相应的TypeConverter,然后调用相应的类型转换方法。比如:
string literalValue = "1981-08-24"; DateTimeConverter dateTypeConverter = newDateTimeConverter(); DateTime dateTimeValue = (DateTime)dateTypeConverter.ConvertFromString(literalValue); literalValue = "02:40:50"; TimeSpanConverter timeSpanConverter = new imeSpanConverter(); TimeSpan timeSpanValue = (TimeSpan imeSpanConverter.ConvertFromString(literalValue);
***一种常见的方法用在将基于某种具体类型的格式化字符串转化成对应的类型,我们可以调用具体类型的静态方法Parse或者TryParse实现类型的转换,比如:
string literalValue = "1981-08-24"; DateTime dateTimeValue1 = DateTime.Parse(literalValue); DateTime dateTimeValue2; if (DateTime.TryParse(literalValue, out dateTimeValue2)) { //... }
二、当类型转换遭遇Nullable<T>类型
Convert几乎实现所有“兼容类型”之间的转换,也可以向Parse方法一样解析具有合法格式的字符串。但是,如果目标类型换成是Nullable<T>类型的时候,类型转换将会失败。比如我们将上面第二个例子的目标类型从int换成int?(Nullable<Int32>):
string literalValue = "123"; try { int? intValue = (int?)Convert.ChangeType(literalValue,typeof(int?)); } catch (InvalidCastException ex) { Console.WriteLine(ex.Message); }
类型转换错误消息会被输出:
Invalid cast from 'System.String' to 'System.Nullable`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]'
实际上,如果你调用Convert的ChangeType方法将任何类型对象转换成Nullable<T>类型,都会抛出出InvalidCastException异常,即使你将T类型转化成Nullable<T>。比如,我们将上面的例子中原数据类型换成int类型:
int intValue1 = 123; try { int? intValue = (int?)Convert.ChangeType(intValue1,typeof(int?)); } catch (InvalidCastException ex) { Console.WriteLine(ex.Message); }
依然会输入类似的错误信息:
Invalid cast from 'System.Int32' to 'System.Nullable`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]'.
而实际上,T类型的对象是可以显式或者隐式转化成Nullable<T>对象的。也就是说,下面代码所表示的类型转换是没有问题的:
int intValue1 = 123; int? intValue2 = intValue1; int? intValue3 = (int?)intValue1;
三、将基于Nullable<T>的类型转换实现在扩展方法中
从上面的介绍我们可以得出这样的结论:如果类型T1和T2能够相互兼容,我们可以借助Convert将T1类型对象转换成T2类型,然后通过显式类型转换进一步转换成Nullable<T2>。我们可以通过这两个步骤实现针对于Nullable<T>类型的转换。为了操作方便,我将此转换逻辑写在针对IConvertible接口的扩展方法中:
public static class ConvertionExtensions { public static T? ConvertTo<T>(this IConvertible convertibleValue) where T : struct { if (null == convertibleValue) { return null; } return (T?)Convert.ChangeType(convertibleValue, typeof(T)); } }
借助于上面这个扩展方法ConvertTo,对于目标类型为Nullable<T>的转换就显得很简单了:
int? intValue = "123".ConvertTo<int>(); double? doubleValue = "123".ConvertTo<double>(); DateTime? dateTimeValue = "1981-08-24".ConvertTo<DateTime>();
四、进一步完善扩展方法ConvertTo
上面定义的扩展方法只能完成针对目标类型为Nullable<T>的转换。现在我们来进一步完善它,让这个方法可以实现任意类型之间的转换。下面是我们新版本的ConvertTo方法的定义:
public static T ConvertTo<T>(this IConvertible convertibleValue) { if (null == convertibleValue) { return default(T); } if (!typeof(T).IsGenericType) { return (T)Convert.ChangeType(convertibleValue, typeof(T)); } else { Type genericTypeDefinition = typeof(T).GetGenericTypeDefinition(); if (genericTypeDefinition == typeof(Nullable<>)) { return (T)Convert.ChangeType(convertibleValue, Nullable.GetUnderlyingType(typeof(T))); } } throw new InvalidCastException(string.Format("Invalid cast from type \"{0}\" to type \"{1}\".", convertibleValue.GetType().FullName, typeof(T).FullName)); }
在上面的方法中,我们首先需要确定目标类型是否是Nullable<T>,这个可以通过调用Type对象的GetGenericTypeDefinition方法来判断。如果是,则先要将其转换成对应的基本类型(Nullable<T>的泛型类型)。我们可以通过调用静态类Nullable的静态方法GetUnderlyingType来获得这个基本类型(Underlying Type)。有了这个完善版本的ConvertTo扩展方法,我们就可以进行任意的类型转化了——不论目标类型是可空值类型,还是非可空值类型:
int intValue1 = "123".ConvertTo<int>(); int? intValue2 = "123".ConvertTo<int?>(); DateTime dateTimeValue1 = "1981-08-24".ConvertTo<DateTime>(); DateTime? dateTimeValue2 = "1981-08-24".ConvertTo<DateTime?>();
五、谈谈NullableConverter
上面谈到TypeConverter这个类型,并且说到它具有一系列针对具体数据类型的子类。其中一个子类就是NullableConverter,故名思义,这个TypeConverter专门用于Nullable<T>的类型转换。使用该类实现针对可空值类型的转换很方便,比如:
string literalValue = "1981-08-24"; NullableConverter converter = new NullableConverter(typeof(DateTime?)); DateTime? dateTimevalue = (DateTime?)converter.ConvertFromString(literalValue);
关于如何分析Nullable<T>的类型转换问题就分享到这里啦,希望上述内容能够让大家有所提升。如果想要学习更多知识,请大家多多留意小编的更新。谢谢大家关注一下编程网网站!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341