Der beste Weg, um zu testen, ob ein generischer Typ eine Zeichenfolge ist?(C#)

StackOverflow https://stackoverflow.com/questions/31498

  •  09-06-2019
  •  | 
  •  

Frage

Ich habe eine generische Klasse, die jeden Typ, ob primitiv oder anders, zulassen sollte.Das einzige Problem dabei ist die Verwendung default(T).Wenn Sie default für einen Werttyp oder eine Zeichenfolge aufrufen, wird dieser auf einen sinnvollen Wert (z. B. eine leere Zeichenfolge) initialisiert.Wenn du anrufst default(T) Bei einem Objekt wird null zurückgegeben.Aus verschiedenen Gründen müssen wir sicherstellen, dass wir eine Standardinstanz des Typs haben, wenn es sich nicht um einen primitiven Typ handelt. nicht Null.Hier ist Versuch 1:

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

Problem: String ist kein Werttyp, verfügt aber über keinen parameterlosen Konstruktor.Die aktuelle Lösung lautet also:

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

Aber das fühlt sich wie eine Flickschusterei an.Gibt es eine schönere Möglichkeit, mit dem String-Fall umzugehen?

War es hilfreich?

Lösung

Beachten Sie, dass default(string) null und nicht string.Empty ist.Möglicherweise möchten Sie einen Sonderfall in Ihrem Code:

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

Andere Tipps

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

Ungetestet, aber das erste, was mir in den Sinn kam.

Du kannst den ... benutzen Typschlüssel Aufzählung.Rufen Sie die GetTypeCode-Methode für Klassen auf, die die IConvertible-Schnittstelle implementieren, um den Typcode für eine Instanz dieser Klasse abzurufen.IConvertible wird durch Boolean, SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Single, Double, Decimal, DateTime, Char und String implementiert, sodass Sie damit nach primitiven Typen suchen können.Weitere Infos zu „Generische Typprüfung".

Persönlich mag ich Methodenüberladung:

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

Die Diskussion für String funktioniert hier nicht.

Ich musste den folgenden Code für Generika haben, damit es funktionierte:

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

    }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top