c# - una - ¿Cómo puedo saber si un tipo es de tipo "simple"? es decir, tiene un valor único
view lenta mysql (6)
typeof(string).IsPrimitive == false
typeof(int).IsPrimitive == true
typeof(MyClass).IsClass == true
typeof(string).IsClass == true
typeof(string).IsByRef == false
typeof(MyClass).IsByRef == true // correction: should be false (see comments below)
Tengo un método que ejemplifica una nueva instancia de T y, si es una clase "compleja", rellena sus propiedades de un conjunto de valores de datos de origen.
(a) Si T es un tipo simple (por ejemplo, una cadena o un int o cualquier otra cosa similar), se debe realizar una conversión rápida de los datos de origen a T.
(b) Si T es una clase (pero no algo simple como una cadena), entonces usaré Activator.CreateInstance y reflexionaré un poco para llenar los campos.
¿Hay una manera rápida y simple de decir si debo usar el método (a) o el método (b)? Esta lógica se usará dentro de un método genérico con T como el argumento de tipo.
Además de Stefan Steinegger, responda: en .NET Core, .IsPrimitive, etc. ya no son miembros de Type, ahora son miembros de TypeInfo. Entonces su solución se convertirá en:
bool IsSimple(TypeInfo type)
{
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
{
// nullable type, check if the nested type is simple.
return IsSimple((type.GetGenericArguments()[0]).GetTypeInfo());
}
return type.IsPrimitive
|| type.IsEnum
|| type.Equals(typeof(string))
|| type.Equals(typeof(decimal));
}
Cadena es probablemente un caso especial.
Creo que lo haría ...
bool IsSimple(Type type)
{
return type.IsPrimitive
|| type.Equals(typeof(string));
}
Editar:
A veces necesitas cubrir algunos casos más, como enumeraciones y decimales. Los enumeraciones son un tipo especial de tipo en C #. Los decimales son estructuras como cualquier otra. El problema con las estructuras es que pueden ser complejas, pueden ser tipos definidos por el usuario, pueden ser solo un número. Entonces no tienes más oportunidad que conocerlos para diferenciar.
bool IsSimple(Type type)
{
return type.IsPrimitive
|| type.IsEnum
|| type.Equals(typeof(string))
|| type.Equals(typeof(decimal));
}
Manejar contrapartes que aceptan nulos es también un poco complicado. El nullable en sí es una estructura.
bool IsSimple(Type type)
{
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
{
// nullable type, check if the nested type is simple.
return IsSimple(type.GetGenericArguments()[0]);
}
return type.IsPrimitive
|| type.IsEnum
|| type.Equals(typeof(string))
|| type.Equals(typeof(decimal));
}
Prueba:
Assert.IsTrue(IsSimple(typeof(string)));
Assert.IsTrue(IsSimple(typeof(int)));
Assert.IsTrue(IsSimple(typeof(decimal)));
Assert.IsTrue(IsSimple(typeof(float)));
Assert.IsTrue(IsSimple(typeof(StringComparison))); // enum
Assert.IsTrue(IsSimple(typeof(int?)));
Assert.IsTrue(IsSimple(typeof(decimal?)));
Assert.IsTrue(IsSimple(typeof(StringComparison?)));
Assert.IsFalse(IsSimple(typeof(object)));
Assert.IsFalse(IsSimple(typeof(Point))); // struct in System.Drawing
Assert.IsFalse(IsSimple(typeof(Point?)));
Assert.IsFalse(IsSimple(typeof(StringBuilder))); // reference type
Nota para .NET Core
Como señala DucoJ en su respuesta , algunos de los métodos utilizados ya no están disponibles en la clase Type
en .NET core más.
Código fijo (espero que funcione, no pude probarlo. De lo contrario, comentar):
bool IsSimple(Type type)
{
var typeInfo = type.GetTypeInfo();
if (typeInfo.IsGenericType && typeInfo.GetGenericTypeDefinition() == typeof(Nullable<>))
{
// nullable type, check if the nested type is simple.
return IsSimple(typeInfo.GetGenericArguments()[0]);
}
return typeInfo.IsPrimitive
|| typeInfo.IsEnum
|| type.Equals(typeof(string))
|| type.Equals(typeof(decimal));
}
Hay un tipo más general que primitivo, ValueType abarca mucho más que primitivo, como enumeraciones, decimales y otras cosas como ValueType . A continuación hay una función que escribí para identificar tipos complejos, que pueden ajustarse a sus necesidades.
public static bool IsComplex(Type typeIn)
{
if (typeIn.IsSubclassOf(typeof(System.ValueType)) || typeIn.Equals(typeof(string))) //|| typeIn.IsPrimitive
return false;
else
return true;
}
Las cadenas no son primitivas, si no recuerdo mal. aunque hay una palabra clave para ella, una cadena es un objeto. Su llamada a IsPrimitive le dirá con precisión si algo es primitivo.
Perdón por resucitar un hilo muy antiguo, pero dado que todavía ocupa un lugar destacado en las búsquedas web en Google, quiero que se agregue una solución más directa y efectiva:
if(System.Type.GetTypeCode(typeof(int)) == TypeCode.Object) {
// Do what you will...
}
Puede que no importe, pero parece que estás dejando de lado algunos casos:
- Tipos complejos que tienen conversiones
- Tipos de valor que no tienen un constructor sin parámetros. Ejemplo a continuación:
Probablemente haya más, pero creo que estás dividiendo el espacio problemático de una manera excesivamente restrictiva.
public class Person {
private string _name;
private int _age;
public Person(string name, int age) {_name = name; _age = age;}
// Remainder of value implementation
}