c# - serializar - serialize entity to xml
Verificando si un objeto es un nĂºmero en C# (10)
Aproveche la propiedad IsPrimitive para hacer un método de extensión útil:
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);
}
EDITAR: Corregido según los comentarios. Los genéricos se eliminaron ya que .GetType () encajona los tipos de valor. También se incluye la corrección para valores que aceptan valores NULL.
Me gustaría comprobar si un objeto es un número para que .ToString()
resulte en una cadena que contenga dígitos y +
, -
.ToString()
¿Es posible mediante el simple control de tipos en .net (como: if (p is Number)
)?
O ¿Debería convertir a cadena y luego analizar para duplicar?
Actualización: para aclarar que mi objeto es int, uint, float, double, etc., no es una cadena. Estoy intentando hacer una función que serialice cualquier objeto a xml de esta manera:
<string>content</string>
o
<numeric>123.3</numeric>
o plantea una excepción.
En lugar de hacer la suya propia, la forma más confiable de saber si un tipo integrado es numérico probablemente sea hacer referencia a Microsoft.VisualBasic
y llamar a Information.IsNumeric(object value)
. La implementación maneja una cantidad de casos sutiles tales como char[]
y cadenas HEX y OCT.
Hay algunas excelentes respuestas arriba. Aquí hay una solución todo en uno. Tres sobrecargas para diferentes circunstancias.
// 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)); }
Hay tres conceptos diferentes allí:
- para comprobar si se trata de un número (es decir, un valor numérico (normalmente enmarcado)), compruebe que el tipo
is
- por ejemplo,if(obj is int) {...}
- para verificar si una cadena se puede analizar como un número; use
TryParse()
- pero si el objeto no es un número o una cadena, pero sospecha que
ToString()
podría dar algo que se parece a un número, entonces llame aToString()
y trátelo como una cadena
En los dos primeros casos, es probable que tenga que manejar por separado cada tipo numérico que desee admitir ( double
/ decimal
/ int
); cada uno tiene diferentes rangos y precisión, por ejemplo.
También puede ver regex para un control rápido.
Puede usar un código como este:
if (n is IConvertible)
return ((IConvertible) n).ToDouble(CultureInfo.CurrentCulture);
else
// Cannot be converted.
Si su objeto es una cadena, esto no analizará la cadena. Sin embargo, si su objeto es Int32, Single, Double etc., realizará la conversión.
Sí, esto funciona:
object x = 1;
Assert.That(x is int);
Para un número de coma flotante, debe probar usando el tipo de flotador:
object x = 1f;
Assert.That(x is float);
Si tu requerimiento es realmente
.ToString () daría como resultado una cadena que contiene dígitos y +, - ,.
y quiere usar double.TryParse, entonces necesita usar la sobrecarga que toma un parámetro NumberStyles y asegúrese de estar usando la cultura invariante.
Por ejemplo, para un número que puede tener un signo inicial, sin espacio en blanco inicial o posterior, separador de miles y separador decimal de período, use:
NumberStyles style =
NumberStyles.AllowLeadingSign |
NumberStyles.AllowDecimalPoint |
double.TryParse(input, style, CultureInfo.InvariantCulture, out result);
Simplemente necesitará hacer una verificación de tipo para cada uno de los tipos numéricos básicos.
Aquí hay un método de extensión que debería hacer el trabajo:
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;
}
Esto debería cubrir todos los tipos numéricos.
Actualizar
Parece que realmente quieres analizar el número de una cadena durante la deserialización. En este caso, probablemente sea mejor usar double.TryParse
.
string value = "123.3";
double num;
if (!double.TryParse(value, out num))
throw new InvalidOperationException("Value is not a number.");
Por supuesto, esto no manejaría enteros muy largos / decimales largos, pero si ese es el caso solo necesita agregar llamadas adicionales a long.TryParse
/ decimal.TryParse
/ lo que sea.
Suponiendo que su entrada es una cadena ...
Hay 2 formas:
usa Double.TryParse ()
double temp;
bool isNumber = Double.TryParse(input, out temp);
usar Regex
bool isNumber = Regex.IsMatch(input,@"-?/d+(/./d+)?");
Tomado del blog de 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);
}