Pregunta

Tengo una clase genérica que debería permitir cualquier tipo, primitivo o no.El único problema con esto es usar default(T).Cuando llama a default en un tipo de valor o una cadena, lo inicializa a un valor razonable (como una cadena vacía).Cuando usted llama default(T) en un objeto, devuelve nulo.Por varias razones, debemos asegurarnos de que si no es un tipo primitivo, tendremos una instancia predeterminada del tipo. no nulo.Aquí está el intento 1:

T createDefault()
{
    if(typeof(T).IsValueType)
    {
        return default(T);
    }
    else
    {
        return Activator.CreateInstance<T>();
    }
}

Problema: la 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 parece una pifia.¿Existe una forma mejor de manejar el caso de cadenas?

¿Fue útil?

Solución

Tenga en cuenta que default(string) es nulo, no string.Empty.Es posible que desee un caso especial en su código:

if (typeof(T) == typeof(String)) return (T)(object)String.Empty;

Otros consejos

if (typeof(T).IsValueType || typeof(T) == typeof(String))
{
     return default(T);
}
else
{
     return Activator.CreateInstance<T>();
}

No probado, pero lo primero que me vino a la mente.

Puedes usar el Código de tipo enumeración.Llame al método GetTypeCode en clases que implementan la interfaz IConvertible para obtener el código de tipo para una instancia de esa clase.IConvertible se implementa mediante Boolean, SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Single, Double, Decimal, DateTime, Char y String, por lo que puede verificar tipos primitivos usando esto.Más información sobre "Comprobación de tipo genérico".

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();
  }
}

La discusión sobre String no funciona aquí.

Tenía que tener el siguiente código para genéricos para que funcionara:

   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>();
            } 
        } 

    }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top