net - remarks c#
¿La mejor manera de probar si un tipo genérico es una cadena?(DO#) (5)
Tengo una clase genérica que debe permitir cualquier tipo, primitivo o de otro tipo. El único problema con esto es usar el default(T)
. Cuando llama por defecto a un tipo de valor o una cadena, lo inicializa a un valor razonable (como una cadena vacía). Cuando llama por default(T)
a un objeto, devuelve nulo. Por diversas razones, debemos asegurarnos de que, si no es un tipo primitivo, tendremos una instancia predeterminada del tipo, no nula. Aquí está el intento 1:
T createDefault()
{
if(typeof(T).IsValueType)
{
return default(T);
}
else
{
return Activator.CreateInstance<T>();
}
}
Problema: cadena no es un tipo de valor, pero no tiene un constructor sin parámetros. Entonces, la solución actual es:
T createDefault()
{
if(typeof(T).IsValueType || typeof(T).FullName == "System.String")
{
return default(T);
}
else
{
return Activator.CreateInstance<T>();
}
}
Pero esto se siente como un obstáculo. ¿Hay alguna manera más agradable de manejar la caja de cuerdas?
La discusión sobre String no está funcionando aquí.
Tenía que tener el siguiente código de genéricos para que funcione:
private T createDefault()
{
{
if(typeof(T).IsValueType)
{
return default(T);
}
else if (typeof(T).Name == "String")
{
return (T)Convert.ChangeType(String.Empty,typeof(T));
}
else
{
return Activator.CreateInstance<T>();
}
}
}
Personalmente, me gusta la sobrecarga de métodos:
public static class Extensions {
public static String Blank(this String me) {
return String.Empty;
}
public static T Blank<T>(this T me) {
var tot = typeof(T);
return tot.IsValueType
? default(T)
: (T)Activator.CreateInstance(tot)
;
}
}
class Program {
static void Main(string[] args) {
Object o = null;
String s = null;
int i = 6;
Console.WriteLine(o.Blank()); //"System.Object"
Console.WriteLine(s.Blank()); //""
Console.WriteLine(i.Blank()); //"0"
Console.ReadKey();
}
}
Puede usar la enumeración de TypeCode . Llame al método GetTypeCode en las clases que implementan la interfaz IConvertible para obtener el código de tipo para una instancia de esa clase. IConvertible es implementado por Boolean, SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Simple, Doble, Decimal, DateTime, Char y String, por lo que puede verificar los tipos primitivos usando esto. Más información sobre " Comprobación de tipo genérico ".
Tenga en cuenta que el valor predeterminado (cadena) es nulo, no de cadena. Vacío. Es posible que desee un caso especial en su código:
if (typeof(T) == typeof(String)) return (T)(object)String.Empty;
if (typeof(T).IsValueType || typeof(T) == typeof(String))
{
return default(T);
}
else
{
return Activator.CreateInstance<T>();
}
No probado, pero lo primero que se me vino a la mente.