将string转换为可空types(int,double等)

我正在尝试做一些数据转换。 不幸的是,大部分的数据是string,它应该是int或double等等。

所以我得到的是这样的:

double? amount = Convert.ToDouble(strAmount); 

这种方法的问题是,如果strAmount是空的,如果它是空的,我想它为null,所以当我把它添加到数据库的列将是空的。 所以我写了这个:

 double? amount = null; if(strAmount.Trim().Length>0) { amount = Convert.ToDouble(strAmount); } 

现在,这工作正常,但我现在有五行代码,而不是一个。 这使得阅读起来更加困难,尤其是当我有大量的列转换时。

我以为我会使用string类和generics的扩展来传入types,这是因为它可能是一个双精度,或一个整数,或长。 所以我试过这个:

  public static class GenericExtension { public static Nullable<T> ConvertToNullable<T>(this string s, T type) where T: struct { if (s.Trim().Length > 0) { return (Nullable<T>)s; } return null; } } 

但是我得到的错误:不能转换types“string”为“T?”

有没有解决的办法? 我不太熟悉使用generics创build方法。

另外要记住的是,string本身可能是空的。

 public static Nullable<T> ToNullable<T>(this string s) where T: struct { Nullable<T> result = new Nullable<T>(); try { if (!string.IsNullOrEmpty(s) && s.Trim().Length > 0) { TypeConverter conv = TypeDescriptor.GetConverter(typeof(T)); result = (T)conv.ConvertFrom(s); } } catch { } return result; } 

你可以尝试使用下面的扩展方法:

 public static T? GetValueOrNull<T>(this string valueAsString) where T : struct { if (string.IsNullOrEmpty(valueAsString)) return null; return (T) Convert.ChangeType(valueAsString, typeof(T)); } 

这样你可以做到这一点:

 double? amount = strAmount.GetValueOrNull<double>(); int? amount = strAmount.GetValueOrNull<int>(); decimal? amount = strAmount.GetValueOrNull<decimal>(); 

我写了这个genericstypes转换器。 它与Nullable和标准值一起工作,在所有可转换types之间转换 – 不仅仅是string。 它处理你所期望的各种场景(默认值,空值,其他值等)

我已经在几十个生产程序中使用了大约一年,所以它应该是相当稳固的。

  public static T To<T>(this IConvertible obj) { Type t = typeof(T); if (t.IsGenericType && (t.GetGenericTypeDefinition() == typeof(Nullable<>))) { if (obj == null) { return (T)(object)null; } else { return (T)Convert.ChangeType(obj, Nullable.GetUnderlyingType(t)); } } else { return (T)Convert.ChangeType(obj, t); } } public static T ToOrDefault<T> (this IConvertible obj) { try { return To<T>(obj); } catch { return default(T); } } public static bool ToOrDefault<T> (this IConvertible obj, out T newObj) { try { newObj = To<T>(obj); return true; } catch { newObj = default(T); return false; } } public static T ToOrOther<T> (this IConvertible obj, T other) { try { return To<T>(obj); } catch { return other; } } public static bool ToOrOther<T> (this IConvertible obj, out T newObj, T other) { try { newObj = To<T>(obj); return true; } catch { newObj = other; return false; } } public static T ToOrNull<T> (this IConvertible obj) where T : class { try { return To<T>(obj); } catch { return null; } } public static bool ToOrNull<T> (this IConvertible obj, out T newObj) where T : class { try { newObj = To<T>(obj); return true; } catch { newObj = null; return false; } } 

那这个呢:

 double? amount = string.IsNullOrEmpty(strAmount) ? (double?)null : Convert.ToDouble(strAmount); 

当然,这并没有考虑到转换失败。

你可能想尝试:

 TypeConverter conv = TypeDescriptor.GetConverter(typeof(int)); conv.ConvertFrom(mystring); 

做你自己的空检查并返回int? 如有必要。 你也想在一个try {}

给这个一个镜头…

 public delegate bool TryParseDelegate<T>(string data, out T output); public static T? ToNullablePrimitive<T>(this string data, TryParseDelegate<T> func) where T:struct { string.IsNullOrEmpty(data) return null; T output; if (func(data, out output)) { return (T?)output; } return null; } 

那就这样称呼吧

 void doStuff() { string foo = "1.0"; double? myDouble = foo.ToNullablePrimitive<double>(double.TryParse); foo = "1"; int? myInt = foo.ToNullablePrimitive<int>(int.TryParse); foo = "haha"; int? myInt2 = foo.ToNullablePrimitive<int>(int.TryParse); } 

我喜欢乔尔的回答,但我已经修改了一些,因为我不喜欢吃例外。

  /// <summary> /// Converts a string to the specified nullable type. /// </summary> /// <typeparam name="T">The type to convert to</typeparam> /// <param name="s">The string to convert</param> /// <returns>The nullable output</returns> public static T? ToNullable<T>(this string s) where T : struct { if (string.IsNullOrWhiteSpace(s)) return null; TypeConverter conv = TypeDescriptor.GetConverter(typeof (T)); return (T) conv.ConvertFrom(s); } /// <summary> /// Attempts to convert a string to the specified nullable primative. /// </summary> /// <typeparam name="T">The primitive type to convert to</typeparam> /// <param name="data">The string to convert</param> /// <param name="output">The nullable output</param> /// <returns> /// True if conversion is successfull, false otherwise. Null and whitespace will /// be converted to null and return true. /// </returns> public static bool TryParseNullable<T>(this string data, out T? output) where T : struct { try { output = data.ToNullable<T>(); return true; } catch { output = null; return false; } } 

你可以使用下面的对象,不幸的是这不能用于string。

 double? amount = (double?)someObject; 

我用它来包装一个属性(在一个基本页面)的会话variables..所以我的实际用法是(在我的基本页面):

 public int? OrganisationID { get { return (int?)Session[Constants.Session_Key_OrganisationID]; } set { Session[Constants.Session_Key_OrganisationID] = value; } } 

我能够检查页面逻辑中的空值:

 if (base.OrganisationID == null) // do stuff 

这是没有办法的。 可空,以及你的方法,仅限于使用值types作为它的参数。 String是一个引用types,因此与这个声明不兼容。

 public static class GenericExtension { public static T? ConvertToNullable<T>(this String s) where T : struct { try { return (T?)TypeDescriptor.GetConverter(typeof(T)).ConvertFrom(s); } catch (Exception) { return null; } } } 

有一个通用的解决scheme(任何types)。 可用性很好,但实施应该改进: http : //cleansharp.de/wordpress/2011/05/generischer-typeconverter/

这可以让你编写非常干净的代码,如下所示:

 string value = null; int? x = value.ConvertOrDefault<int?>(); 

并且:

 object obj = 1; string value = null; int x = 5; if (value.TryConvert(out x)) Console.WriteLine("TryConvert example: " + x); bool boolean = "false".ConvertOrDefault<bool>(); bool? nullableBoolean = "".ConvertOrDefault<bool?>(); int integer = obj.ConvertOrDefault<int>(); int negativeInteger = "-12123".ConvertOrDefault<int>(); int? nullableInteger = value.ConvertOrDefault<int?>(); MyEnum enumValue = "SecondValue".ConvertOrDefault<MyEnum>(); MyObjectBase myObject = new MyObjectClassA(); MyObjectClassA myObjectClassA = myObject.ConvertOrDefault<MyObjectClassA>(); 

这是根据接受的答案。 我删除了try / catch,以确保所有的exception都不会被吞没,也不会被处理。 还确保返回variables(在接受的答案中)永远不会被初始化两次。

 public static Nullable<T> ToNullable<T>(this string s) where T: struct { if (!string.IsNullOrWhiteSpace(s)) { TypeConverter conv = TypeDescriptor.GetConverter(typeof(T)); return (T)conv.ConvertFrom(s); } return default(Nullable<T>); } 

我的例子为anonimoustypes:

 private object ConvertNullable(object value, Type nullableType) { Type resultType = typeof(Nullable<>).MakeGenericType(nullableType.GetGenericArguments()); return Activator.CreateInstance(resultType, Convert.ChangeType(value, nullableType.GetGenericArguments()[0])); } ... Type anonimousType = typeof(Nullable<int>); object nullableInt1 = ConvertNullable("5", anonimousType); // or evident Type Nullable<int> nullableInt2 = (Nullable<int>)ConvertNullable("5", typeof(Nullable<int>)); 

另一个变化。 这个

  • 不吞下exception
  • 如果无法从string转换types,则会引发NotSupportedException 。 例如,一个没有types转换器的自定义结构。
  • 否则返回一个(T?)null如果stringparsing失败。 不需要检查空或空白。
 using System.ComponentModel; public static Nullable<T> ToNullable<T>(this string s) where T : struct { var ret = new Nullable<T>(); var conv = TypeDescriptor.GetConverter(typeof(T)); if (!conv.CanConvertFrom(typeof(string))) { throw new NotSupportedException(); } if (conv.IsValid(s)) { ret = (T)conv.ConvertFrom(s); } return ret; } 

让我们再添加一个类似的解决scheme到堆栈中。 这个也parsing枚举,它看起来不错。 非常安全。

 /// <summary> /// <para>More convenient than using T.TryParse(string, out T). /// Works with primitive types, structs, and enums. /// Tries to parse the string to an instance of the type specified. /// If the input cannot be parsed, null will be returned. /// </para> /// <para> /// If the value of the caller is null, null will be returned. /// So if you have "string s = null;" and then you try "s.ToNullable...", /// null will be returned. No null exception will be thrown. /// </para> /// <author>Contributed by Taylor Love (Pangamma)</author> /// </summary> /// <typeparam name="T"></typeparam> /// <param name="p_self"></param> /// <returns></returns> public static T? ToNullable<T>(this string p_self) where T : struct { if (!string.IsNullOrEmpty(p_self)) { var converter = System.ComponentModel.TypeDescriptor.GetConverter(typeof(T)); if (converter.IsValid(p_self)) return (T)converter.ConvertFromString(p_self); if (typeof(T).IsEnum) { T t; if (Enum.TryParse<T>(p_self, out t)) return t;} } return null; } 

https://github.com/Pangamma/PangammaUtilities-CSharp/blob/master/PangammaUtilities/Extensions/ToNullableStringExtension.cs