860 Stimmen

Wie erhält man den Typ von T von einem Mitglied einer generischen Klasse oder Methode?

Nehmen wir an, ich habe ein generisches Mitglied in einer Klasse oder Methode, etwa so:

public class Foo<T>
{
    public List<T> Bar { get; set; }

    public void Baz()
    {
        // get type of T
    }   
}

Wenn ich die Klasse instanziere, wird die T wird MyTypeObject1 Die Klasse hat also eine generische Listeneigenschaft: List<MyTypeObject1> . Dasselbe gilt für eine generische Methode in einer nicht-generischen Klasse:

public class Foo
{
    public void Bar<T>()
    {
        var baz = new List<T>();

        // get type of T
    }
}

Ich würde gerne wissen, welche Art von Objekten die Liste meiner Klasse enthält. Also welche Art von T wird die Listeneigenschaft namens Bar oder die lokale Variable baz enthalten?

Ich kann nicht tun Bar[0].GetType() , da die Liste auch Nullelemente enthalten kann. Wie kann ich das tun?

17voto

Carlos Rodriguez Punkte 179

Bei mir funktioniert das Folgende. Wobei myList eine unbekannte Art von Liste ist.

IEnumerable myEnum = myList as IEnumerable;
Type entryType = myEnum.AsQueryable().ElementType;

1 Stimmen

Ich erhalte die Fehlermeldung, dass ein Typargument erforderlich ist (d.h. <T> )

0 Stimmen

Joseph und andere, um den Fehler loszuwerden, ist es in System.Collections.

1 Stimmen

Für mich ist nur die zweite Zeile erforderlich. A List ist bereits eine Implementierung von IEnumerable also scheint die Besetzung nichts zu bringen. Aber danke, das ist eine gute Lösung.

15voto

Diese können Sie für den Rückgabetyp einer generischen Liste verwenden:

public string ListType<T>(T value)
{
    var valueType = value.GetType().GenericTypeArguments[0].FullName;
    return valueType;
}

9voto

Thomas Punkte 81

El GetGenericArgument() Methode muss auf den Basistyp Ihrer Instanz gesetzt werden (deren Klasse eine generische Klasse ist) myClass<T> ). Andernfalls wird ein Typ[0] zurückgegeben.

Ejemplo:

Myclass<T> instance = new Myclass<T>();
Type[] listTypes = typeof(instance).BaseType.GetGenericArguments();

8voto

Ferenc Mucsi Punkte 71

Bedenken Sie dies:

Ich verwende es, um 20 getippte Listen auf die gleiche Weise zu exportieren:

private void Generate<T>()
{
    T item = (T)Activator.CreateInstance(typeof(T));

    ((T)item as DemomigrItemList).Initialize();

    Type type = ((T)item as DemomigrItemList).AsEnumerable().FirstOrDefault().GetType();
    if (type == null) 
        return;
    if (type != typeof(account)) // Account is listitem in List<account>
    {
        ((T)item as DemomigrItemList).CreateCSV(type);
    }
}

1 Stimmen

Dies funktioniert nicht, wenn T eine abstrakte Oberklasse der eigentlichen hinzugefügten Objekte ist. Nicht zu vergessen, dass nur new T(); würde dasselbe bewirken wie (T)Activator.CreateInstance(typeof(T)); . Dazu müssen Sie Folgendes hinzufügen where T : new() zur Klasse/Funktionsdefinition, aber wenn Sie wollen um Objekte zu erstellen, sollte dies ohnehin geschehen.

0 Stimmen

Außerdem rufen Sie GetType in einem FirstOrDefault Eintrag, was zu einer potenziellen Nullreferenz-Ausnahme führt. Wenn Sie sicher sind, dass mindestens ein Eintrag zurückgegeben wird, warum nicht First stattdessen?

8voto

Ken Smith Punkte 19957

Ich verwende diese Erweiterungsmethode, um etwas Ähnliches zu erreichen:

public static string GetFriendlyTypeName(this Type t)
{
    var typeName = t.Name.StripStartingWith("`");
    var genericArgs = t.GetGenericArguments();
    if (genericArgs.Length > 0)
    {
        typeName += "<";
        foreach (var genericArg in genericArgs)
        {
            typeName += genericArg.GetFriendlyTypeName() + ", ";
        }
        typeName = typeName.TrimEnd(',', ' ') + ">";
    }
    return typeName;
}

public static string StripStartingWith(this string s, string stripAfter)
{
    if (s == null)
    {
        return null;
    }
    var indexOf = s.IndexOf(stripAfter, StringComparison.Ordinal);
    if (indexOf > -1)
    {
        return s.Substring(0, indexOf);
    }
    return s;
}

Sie verwenden es so:

[TestMethod]
public void GetFriendlyTypeName_ShouldHandleReallyComplexTypes()
{
    typeof(Dictionary<string, Dictionary<string, object>>).GetFriendlyTypeName()
        .ShouldEqual("Dictionary<String, Dictionary<String, Object>>");
}

Das ist nicht ganz das, wonach Sie suchen, aber es ist hilfreich, um die Techniken zu demonstrieren.

0 Stimmen

Eine Erklärung wäre angebracht. Z.B.: Was ist der Kern der Sache? Was ist die Idee? Bitte antworten Sie, indem Sie Ihre Antwort bearbeiten, nicht hier in den Kommentaren ( ohne "Bearbeiten:", "Aktualisieren:" oder ähnlich - die Antwort sollte so aussehen, als wäre sie heute geschrieben worden).

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X