![](/img/trans.png)
[英]How to convert double to nullable int, int to nullable int in AutoMapper?
[英]Convert string to nullable type (int, double, etc…)
我正在嘗試進行一些數據轉換。 不幸的是,大部分數據都是字符串,它應該是int或double等等......
所以我得到的是:
double? amount = Convert.ToDouble(strAmount);
這種方法的問題是如果strAmount為空,如果它為空,我希望它等於null,所以當我將它添加到數據庫時,該列將為null。 所以我最后寫了這個:
double? amount = null;
if(strAmount.Trim().Length>0)
{
amount = Convert.ToDouble(strAmount);
}
現在這個工作正常,但我現在有五行代碼而不是一行代碼。 這使得事情變得更難以閱讀,特別是當我有大量的列要轉換時。
我以為我會使用字符串類和泛型的擴展來傳入類型,這是因為它可能是double,或int或long。 所以我嘗試了這個:
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;
}
}
但我收到錯誤:無法將類型'string'轉換為'T?'
有沒有解決的辦法? 我不太熟悉使用泛型創建方法。
要記住的另一件事是字符串本身可能為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;
}
您可以嘗試使用以下擴展方法:
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>();
那這個呢:
double? amount = string.IsNullOrEmpty(strAmount) ? (double?)null : Convert.ToDouble(strAmount);
當然,這並沒有考慮轉換失敗。
我寫了這個泛型轉換器。 它適用於Nullable和標准值,在所有可轉換類型之間進行轉換 - 而不僅僅是字符串。 它處理您期望的各種場景(默認值,空值,其他值等...)
我已經在幾十個生產程序中使用了大約一年,所以它應該非常可靠。
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;
}
}
您可能想嘗試:
TypeConverter conv = TypeDescriptor.GetConverter(typeof(int));
conv.ConvertFrom(mystring);
做你自己的null檢查並返回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);
}
您可以將以下內容與對象一起使用,但不幸的是,這不適用於字符串。
double? amount = (double?)someObject;
我用它來包裝屬性中的會話變量(在基頁上)..所以我的實際用法是(在我的基頁中):
public int? OrganisationID
{
get { return (int?)Session[Constants.Session_Key_OrganisationID]; }
set { Session[Constants.Session_Key_OrganisationID] = value; }
}
我能夠在頁面邏輯中檢查null:
if (base.OrganisationID == null)
// do stuff
我喜歡Joel的回答,但我對它進行了一些修改,因為我不喜歡吃異常。
/// <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;
}
}
這是基於公認答案的東西。 我刪除了try / catch以確保不會吞下所有異常並且不處理。 還要確保返回變量(在接受的答案中)永遠不會被初始化兩次。
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>);
}
沒有辦法解決這個問題。 Nullable以及您的方法僅限於使用值類型作為其參數。 String是引用類型,因此與此聲明不兼容。
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;
}
}
}
有一個通用的解決方案(適用於任何類型)。 可用性很好,但應該改進實施: 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>();
我的anonimous類型的例子:
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>));
另一種變化。 這個
string
轉換類型,則拋出NotSupportedException
。 例如,沒有類型轉換器的自定義結構。 (T?)null
。 無需檢查null或空格。 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;
}
讓我們在堆棧中添加一個類似的解決方案。 這個也解析枚舉,看起來不錯。 非常安全。
/// <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;
}
“ Joel Coehoorn ”提供的通用答案很好。
但是,這是另一種不使用GetConverter...
或try/catch
塊的方式......(我不確定但在某些情況下這可能有更好的性能):
public static class StrToNumberExtensions
{
public static short ToShort(this string s, short defaultValue = 0) => short.TryParse(s, out var v) ? v : defaultValue;
public static int ToInt(this string s, int defaultValue = 0) => int.TryParse(s, out var v) ? v : defaultValue;
public static long ToLong(this string s, long defaultValue = 0) => long.TryParse(s, out var v) ? v : defaultValue;
public static decimal ToDecimal(this string s, decimal defaultValue = 0) => decimal.TryParse(s, out var v) ? v : defaultValue;
public static float ToFloat(this string s, float defaultValue = 0) => float.TryParse(s, out var v) ? v : defaultValue;
public static double ToDouble(this string s, double defaultValue = 0) => double.TryParse(s, out var v) ? v : defaultValue;
public static short? ToshortNullable(this string s, short? defaultValue = null) => short.TryParse(s, out var v) ? v : defaultValue;
public static int? ToIntNullable(this string s, int? defaultValue = null) => int.TryParse(s, out var v) ? v : defaultValue;
public static long? ToLongNullable(this string s, long? defaultValue = null) => long.TryParse(s, out var v) ? v : defaultValue;
public static decimal? ToDecimalNullable(this string s, decimal? defaultValue = null) => decimal.TryParse(s, out var v) ? v : defaultValue;
public static float? ToFloatNullable(this string s, float? defaultValue = null) => float.TryParse(s, out var v) ? v : defaultValue;
public static double? ToDoubleNullable(this string s, double? defaultValue = null) => double.TryParse(s, out var v) ? v : defaultValue;
}
用法如下:
var x1 = "123".ToInt(); //123
var x2 = "abc".ToInt(); //0
var x3 = "abc".ToIntNullable(); // (int?)null
int x4 = ((string)null).ToInt(-1); // -1
int x5 = "abc".ToInt(-1); // -1
var y = "19.50".ToDecimal(); //19.50
var z1 = "invalid number string".ToDoubleNullable(); // (double?)null
var z2 = "invalid number string".ToDoubleNullable(0); // (double?)0
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.