C# 将字符串转换为可空类型(int、double 等...)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/773078/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Convert string to nullable type (int, double, etc...)
提问by Nathan Koop
I am attempting to do some data conversion. Unfortunately, much of the data is in strings, where it should be int's or double, etc...
我正在尝试进行一些数据转换。不幸的是,大部分数据都在字符串中,它应该是 int 或 double 等......
So what I've got is something like:
所以我得到的是这样的:
double? amount = Convert.ToDouble(strAmount);
The problem with this approach is if strAmount is empty, if it's empty I want it to amount to be null, so when I add it into the database the column will be null. So I ended up writing this:
这种方法的问题是如果 strAmount 是空的,如果它是空的,我希望它的数量为空,所以当我将它添加到数据库中时,该列将为空。所以我最终写了这个:
double? amount = null;
if(strAmount.Trim().Length>0)
{
amount = Convert.ToDouble(strAmount);
}
Now this works fine, but I now have five lines of code instead of one. This makes things a little more difficult to read, especially when I have a large amount of columns to convert.
现在这工作正常,但我现在有五行代码而不是一行。这使得阅读起来有点困难,尤其是当我有大量的列要转换时。
I thought I'd use an extension to the string class and generic's to pass in the type, this is because it could be a double, or an int, or a long. So I tried this:
我想我会使用字符串类和泛型的扩展来传递类型,这是因为它可以是双精度型、整数型或长型。所以我试过这个:
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;
}
}
But I get the error: Cannot convert type 'string' to 'T?'
但我收到错误:无法将类型“字符串”转换为“T?”
Is there a way around this? I am not very familiar with creating methods using generics.
有没有解决的办法?我对使用泛型创建方法不是很熟悉。
采纳答案by Joel Coehoorn
Another thing to keep in mind is that the string itself might be null.
要记住的另一件事是字符串本身可能为空。
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;
}
回答by JaredPar
There is no way around this. Nullable, as well as your method, is constrained to using only value types as it's argument. String is a reference type and hence is incompatible with this declaration.
没有办法解决这个问题。Nullable 以及您的方法仅限于仅使用值类型作为参数。String 是引用类型,因此与此声明不兼容。
回答by Andrew Bullock
You might want to try:
您可能想尝试:
TypeConverter conv = TypeDescriptor.GetConverter(typeof(int));
conv.ConvertFrom(mystring);
do your own null check and return int?
if necessary. You'll also want to wrap that in a try {}
做你自己的空检查并int?
在必要时返回。你还想把它包装在一个try {}
回答by John Kraft
What about this:
那这个呢:
double? amount = string.IsNullOrEmpty(strAmount) ? (double?)null : Convert.ToDouble(strAmount);
Of course, this doesn't take into account the convert failing.
当然,这并没有考虑到转换失败。
回答by Michael Meadows
You could try using the below extension method:
您可以尝试使用以下扩展方法:
public static T? GetValueOrNull<T>(this string valueAsString)
where T : struct
{
if (string.IsNullOrEmpty(valueAsString))
return null;
return (T) Convert.ChangeType(valueAsString, typeof(T));
}
This way you can do this:
这样你就可以做到这一点:
double? amount = strAmount.GetValueOrNull<double>();
int? amount = strAmount.GetValueOrNull<int>();
decimal? amount = strAmount.GetValueOrNull<decimal>();
回答by Daniel Brückner
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;
}
}
}
回答by Adam Robinson
Give this a shot...
试一试这个...
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;
}
Then call it like this...
那就这样叫吧……
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);
}
回答by TheSoftwareJedi
I wrote this generic type converter. It works with Nullable and standard values, converting between all convertible types - not just string. It handles all sorts of scenarios that you'd expect (default values, null values, other values, etc...)
我写了这个通用类型转换器。它适用于 Nullable 和标准值,在所有可转换类型之间进行转换 - 而不仅仅是字符串。它处理您期望的各种场景(默认值、空值、其他值等...)
I've been using this for about a year in dozens of production programs, so it should be pretty solid.
我已经在几十个生产程序中使用它大约一年了,所以它应该非常可靠。
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;
}
}
回答by Colin Place
I like Joel's answer, but I've modified it slightly as I'm not a fan of eating exceptions.
我喜欢乔尔的回答,但我稍微修改了它,因为我不喜欢吃例外。
/// <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;
}
}
回答by Pavel Hodek
There is a generic solution (for any type). Usability is good, but implementation should be improved: http://cleansharp.de/wordpress/2011/05/generischer-typeconverter/
有一个通用的解决方案(适用于任何类型)。可用性很好,但实施应该改进:http: //cleansharp.de/wordpress/2011/05/generischer-typeconverter/
This allows you to write very clean code like this:
这允许您编写非常干净的代码,如下所示:
string value = null;
int? x = value.ConvertOrDefault<int?>();
and also:
并且:
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>();