Saya ingin memeriksa apakah sebuah objek adalah angka sehingga .ToString()
akan menghasilkan string yang berisi angka dan +
, -
,.
Apakah mungkin dengan tipe check in sederhana .net (seperti:) if (p is Number)
?
Atau Haruskah saya mengonversi menjadi string, lalu mencoba menguraikan menjadi ganda?
Pembaruan: Untuk memperjelas objek saya adalah int, uint, float, double, dan seterusnya itu bukan string. Saya mencoba membuat fungsi yang akan membuat objek apa pun menjadi xml seperti ini:
<string>content</string>
atau
<numeric>123.3</numeric>
atau ajukan pengecualian.
c#
.net
serialization
xml-serialization
Piotr Czapla
sumber
sumber
Jawaban:
Anda hanya perlu melakukan pemeriksaan tipe untuk setiap tipe numerik dasar.
Berikut adalah metode ekstensi yang seharusnya melakukan pekerjaan itu:
public static bool IsNumber(this object value) { return value is sbyte || value is byte || value is short || value is ushort || value is int || value is uint || value is long || value is ulong || value is float || value is double || value is decimal; }
Ini harus mencakup semua tipe numerik.
Memperbarui
Tampaknya Anda benar-benar ingin mengurai nomor dari string selama deserialisasinya. Dalam hal ini, mungkin lebih baik digunakan
double.TryParse
.string value = "123.3"; double num; if (!double.TryParse(value, out num)) throw new InvalidOperationException("Value is not a number.");
Tentu saja, ini tidak akan menangani bilangan bulat / desimal yang sangat besar, tetapi jika itu masalahnya, Anda hanya perlu menambahkan panggilan tambahan ke
long.TryParse
/decimal.TryParse
/ apa pun.sumber
Diambil dari Blog Scott Hanselman :
public static bool IsNumeric(object expression) { if (expression == null) return false; double number; return Double.TryParse( Convert.ToString( expression , CultureInfo.InvariantCulture) , System.Globalization.NumberStyles.Any , NumberFormatInfo.InvariantInfo , out number); }
sumber
double.Parse(double.MaxValue.ToString())
menyebabkan sebuahOverflowException
. Anda dapat memperbaikinya dengan menyediakan pengubah bolak-balik.ToString("R")
dalam kasus ini, tetapi kelebihan beban tersebut tidak tersedia karenaConvert.ToString(...)
kami tidak tahu jenisnya. Saya tahu ini sedikit kasus pinggiran, tetapi saya tersandung ke dalamnya saat menulis tes untuk.IsNumeric()
ekstensi saya sendiri . "Solusi" saya adalah menambahkan swtich jenis pemeriksaan sebelum mencoba mengurai apa pun, lihat jawaban saya untuk pertanyaan ini untuk kode.Manfaatkan properti IsPrimitive untuk membuat metode ekstensi praktis:
public static bool IsNumber(this object obj) { if (Equals(obj, null)) { return false; } Type objType = obj.GetType(); objType = Nullable.GetUnderlyingType(objType) ?? objType; if (objType.IsPrimitive) { return objType != typeof(bool) && objType != typeof(char) && objType != typeof(IntPtr) && objType != typeof(UIntPtr); } return objType == typeof(decimal); }
EDIT: Diperbaiki sesuai komentar. Obat generik telah dihapus sejak jenis nilai kotak .GetType (). Juga termasuk perbaikan untuk nilai nullable.
sumber
object
danstring
bukan tipe primitif.Ada beberapa jawaban bagus di atas. Berikut ini solusi lengkap. Tiga kelebihan beban untuk keadaan yang berbeda.
// Extension method, call for any object, eg "if (x.IsNumeric())..." public static bool IsNumeric(this object x) { return (x==null ? false : IsNumeric(x.GetType())); } // Method where you know the type of the object public static bool IsNumeric(Type type) { return IsNumeric(type, Type.GetTypeCode(type)); } // Method where you know the type and the type code of the object public static bool IsNumeric(Type type, TypeCode typeCode) { return (typeCode == TypeCode.Decimal || (type.IsPrimitive && typeCode != TypeCode.Object && typeCode != TypeCode.Boolean && typeCode != TypeCode.Char)); }
sumber
Daripada menggulung sendiri, cara paling andal untuk mengetahui apakah tipe bawaan adalah numerik mungkin dengan referensi
Microsoft.VisualBasic
dan panggilanInformation.IsNumeric(object value)
. Implementasinya menangani sejumlah kasus halus sepertichar[]
string HEX dan OCT.sumber
Ada tiga konsep berbeda di sana:
is
- misalnyaif(obj is int) {...}
TryParse()
ToString()
mungkin memberikan sesuatu yang terlihat seperti angka, maka panggilToString()
dan perlakukan sebagai stringDalam kedua kasus pertama, Anda mungkin harus menangani secara terpisah setiap jenis numerik yang ingin Anda dukung (
double
/decimal
/int
) - masing-masing memiliki rentang dan akurasi yang berbeda, misalnya.Anda juga bisa melihat regex untuk pemeriksaan kasar cepat.
sumber
Dengan asumsi masukan Anda adalah string ...
Ada 2 cara:
gunakan Double.TryParse ()
double temp; bool isNumber = Double.TryParse(input, out temp);
gunakan Regex
bool isNumber = Regex.IsMatch(input,@"-?\d+(\.\d+)?");
sumber
Anda bisa menggunakan kode seperti ini:
if (n is IConvertible) return ((IConvertible) n).ToDouble(CultureInfo.CurrentCulture); else // Cannot be converted.
Jika objek Anda adalah
Int32
,Single
,Double
dll itu akan melakukan konversi. Juga, sebuah string mengimplementasikanIConvertible
tetapi jika string tersebut tidak dapat diubah menjadi double maka aFormatException
akan dilempar.sumber
Jika kebutuhan Anda benar-benar
dan Anda ingin menggunakan double.TryParse maka Anda perlu menggunakan overload yang mengambil parameter NumberStyles, dan pastikan Anda menggunakan budaya invarian.
Misalnya untuk angka yang mungkin memiliki tanda awal, tidak ada spasi di depan atau di belakang, tidak ada pemisah ribuan dan pemisah desimal titik, gunakan:
NumberStyles style = NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint | double.TryParse(input, style, CultureInfo.InvariantCulture, out result);
sumber
Saat menulis
object.IsNumeric()
metode ekstensi saya sendiri berdasarkan jawaban Saul Dolgin untuk pertanyaan ini, saya mengalami masalah potensial di mana Anda akan mendapatkanOverflowException
jika Anda mencobanya dengandouble.MaxValue
ataudouble.MinValue
."Solusi" saya adalah menggabungkan jawaban yang diterima dari Noldorin dengan jawaban dari Saul Dolgin dan menambahkan sakelar pencocokan pola sebelum mencoba mengurai apa pun (dan menggunakan beberapa kebaikan C # 7 untuk sedikit merapikan):
public static bool IsNumeric(this object obj) { if (obj == null) return false; switch (obj) { case sbyte _: return true; case byte _: return true; case short _: return true; case ushort _: return true; case int _: return true; case uint _: return true; case long _: return true; case ulong _: return true; case float _: return true; case double _: return true; case decimal _: return true; } string s = Convert.ToString(obj, CultureInfo.InvariantCulture); return double.TryParse(s, NumberStyles.Any, NumberFormatInfo.InvariantInfo, out double _); }
sumber
Ya, ini berfungsi:
object x = 1; Assert.That(x is int);
Untuk bilangan floating point, Anda harus menguji menggunakan tipe float:
object x = 1f; Assert.That(x is float);
sumber