Saya mencoba melakukan beberapa konversi data. Sayangnya, banyak datanya dalam string, yang seharusnya int atau double, dll ...
Jadi yang saya punya adalah seperti:
double? amount = Convert.ToDouble(strAmount);
Masalah dengan pendekatan ini adalah jika strAmount kosong, jika kosong saya ingin nilainya menjadi nol, jadi ketika saya menambahkannya ke dalam database, kolom akan menjadi null. Jadi saya akhirnya menulis ini:
double? amount = null;
if(strAmount.Trim().Length>0)
{
amount = Convert.ToDouble(strAmount);
}
Sekarang ini berfungsi dengan baik, tetapi sekarang saya memiliki lima baris kode, bukan satu. Ini membuat hal-hal menjadi sedikit lebih sulit untuk dibaca, terutama ketika saya memiliki banyak kolom untuk diubah.
Saya pikir saya akan menggunakan ekstensi ke kelas string dan generik untuk meneruskan tipe, ini karena bisa jadi ganda, atau int, atau panjang. Jadi saya mencoba ini:
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;
}
}
Tapi saya mendapatkan kesalahan: Tidak dapat mengubah jenis 'string' menjadi 'T?'
Apakah ada jalan keluarnya? Saya tidak terlalu terbiasa dengan membuat metode menggunakan obat generik.
sumber
Jawaban:
Hal lain yang perlu diingat adalah bahwa string itu sendiri mungkin nol.
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; }
sumber
Anda dapat mencoba menggunakan metode ekstensi di bawah ini:
public static T? GetValueOrNull<T>(this string valueAsString) where T : struct { if (string.IsNullOrEmpty(valueAsString)) return null; return (T) Convert.ChangeType(valueAsString, typeof(T)); }
Dengan cara ini Anda dapat melakukan ini:
double? amount = strAmount.GetValueOrNull<double>(); int? amount = strAmount.GetValueOrNull<int>(); decimal? amount = strAmount.GetValueOrNull<decimal>();
sumber
Bagaimana dengan ini:
double? amount = string.IsNullOrEmpty(strAmount) ? (double?)null : Convert.ToDouble(strAmount);
Tentu saja, ini tidak memperhitungkan kegagalan konversi.
sumber
Saya menulis konverter tipe generik ini. Ia bekerja dengan nilai Nullable dan standar, mengonversi di antara semua jenis konversi - bukan hanya string. Ini menangani semua jenis skenario yang Anda harapkan (nilai default, nilai null, nilai lain, dll ...)
Saya telah menggunakan ini selama sekitar satu tahun di lusinan program produksi, jadi ini seharusnya cukup 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; } }
sumber
OutOfMemoryException
jika Anda tidak dapat mempersempitnya menjadi satu set tipe pengecualian tetap.Anda mungkin ingin mencoba:
TypeConverter conv = TypeDescriptor.GetConverter(typeof(int)); conv.ConvertFrom(mystring);
lakukan pemeriksaan nol Anda sendiri dan kembalikan
int?
jika perlu. Anda juga ingin membungkusnya dengan filetry {}
sumber
Coba ini ...
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; }
Lalu sebut saja seperti ini ...
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); }
sumber
Saya suka jawaban Joel, tapi saya telah mengubahnya sedikit karena saya bukan penggemar makan pengecualian.
/// <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; } }
sumber
Anda dapat menggunakan berikut ini dengan objek, sayangnya ini tidak berfungsi dengan string.
double? amount = (double?)someObject;
Saya menggunakannya untuk membungkus variabel sesi di properti (di halaman dasar) .. jadi penggunaan aktual saya adalah (di halaman dasar saya):
public int? OrganisationID { get { return (int?)Session[Constants.Session_Key_OrganisationID]; } set { Session[Constants.Session_Key_OrganisationID] = value; } }
Saya dapat memeriksa null di logika halaman:
if (base.OrganisationID == null) // do stuff
sumber
CType(Object, Nullable(Of Double))
berfungsi dengan baik dengan stringTidak ada jalan lain. Nullable, serta metode Anda, dibatasi untuk hanya menggunakan tipe nilai sebagai argumennya. String adalah tipe referensi dan karenanya tidak kompatibel dengan deklarasi ini.
sumber
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; } } }
sumber
Ada solusi umum (untuk semua jenis). Kegunaannya bagus, tetapi implementasi harus ditingkatkan: http://cleansharp.de/wordpress/2011/05/generischer-typeconverter/
Ini memungkinkan Anda untuk menulis kode yang sangat bersih seperti ini:
string value = null; int? x = value.ConvertOrDefault<int?>();
dan juga:
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>();
sumber
typeName.IndexOf
? Benarkah?) Dan perilaku aneh (TryConvert
fungsi yang ditampilkan bahkan tidak menangani nilai null dengan benar).Ini sesuatu berdasarkan jawaban yang diterima. Saya menghapus coba / tangkap untuk memastikan semua pengecualian tidak tertelan dan tidak ditangani. Juga pastikan bahwa variabel return (dalam jawaban yang diterima) tidak pernah diinisialisasi dua kali secara gratis.
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>); }
sumber
Contoh saya untuk tipe 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>));
sumber
Variasi lainnya. Yang ini
NotSupportedException
jika tipe tidak dapat dikonversistring
. Misalnya, struct kustom tanpa pengonversi tipe.(T?)null
jika string gagal untuk mengurai. Tidak perlu memeriksa null atau whitespace.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; }
sumber
Mari tambahkan satu lagi solusi serupa ke tumpukan. Yang ini juga mengurai enum, dan terlihat bagus. Sangat aman.
/// <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
sumber
Jawaban umum yang diberikan oleh " Joel Coehoorn " itu bagus.
Tapi, ini adalah cara lain tanpa menggunakan itu
GetConverter...
atautry/catch
blok ... (saya tidak yakin tetapi ini mungkin memiliki kinerja yang lebih baik dalam beberapa kasus):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; }
Penggunaannya adalah sebagai berikut:
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
sumber
TypeDescriptor.GetConverter
... kode-kode itu. Ini hanyalah cara lain.