Kaip gauti T tipą iš bendros klasės ar metodo nario?

Tarkime, kad turiu bendrą klasės ar metodo elementą, todėl:

 public class Foo<T> { public List<T> Bar { get; set; } public void Baz() { // get type of T } } 

Kai sukuriu klasės egzempliorių, T tampa MyTypeObject1 , todėl klasė turi bendrą sąrašo ypatybę: List<MyTypeObject1> . Tas pats pasakytina ir apie bendrą metodą vienodoje klasėje:

 public class Foo { public void Bar<T>() { var baz = new List<T>(); // get type of T } } 

Norėčiau sužinoti, kokie objektai yra mano klasėje. Taigi sąrašo ypatybė, vadinama „ Bar arba vietinis baz kintamasis, yra T tipo?

Negaliu padaryti Bar[0].GetType() , nes sąraše gali būti nulinių elementų. Kaip tai padaryti?

584
17 февр. Patrick Desjardins paklausė 17 vasario mėn. 2009-02-17 18:24 '09 at 18:24 2009-02-17 18:24
@ 16 atsakymų

Jei suprantu teisingai, jūsų sąrašas turi tokį patį parametrą kaip ir pati konteinerių klasė. Jei taip, tada:

 Type typeParameterType = typeof(T); 

Jei esate laimingoje situacijoje su object kaip tipo parametru, žr.

580
17 февр. Atsakymas pateikiamas Tamas Czinege 17 vasaris. 2009-02-17 18:27 '09 18:27 2009-02-17 18:27

(Pastaba: manau, kad viskas, ką žinote, yra object arba IList ar panašus, ir kad vykdymo metu šis sąrašas gali būti bet kokio tipo)

Jei žinote, kad tai yra List<T> , tada:

 Type type = abc.GetType().GetGenericArguments()[0]; 

Kita galimybė - peržiūrėti rodyklę:

border=0
 Type type = abc.GetType().GetProperty("Item").PropertyType; 

Naujo TypeInfo naudojimas:

 using System.Reflection; // ... var type = abc.GetType().GetTypeInfo().GenericTypeArguments[0]; 
478
17 февр. Atsakymą pateikė Marc Gravell , vasario 17 d. 2009-02-17 18:26 '09, 06:26 pm 2009-02-17 18:26

Naudodami šį išplėtimo būdą galite palikti be atspindžio:

 public static Type GetListType<T>(this List<T> _) { return typeof(T); } 

Arba daugiau:

 public static Type GetEnumeratedType<T>(this IEnumerable<T> _) { return typeof(T); } 

Naudoti:

 List<string> list = new List<string> { "a", "b", "c" }; IEnumerable<string> strings = list; IEnumerable<object> objects = list; Type listType = list.GetListType(); // string Type stringsType = strings.GetEnumeratedType(); // string Type objectsType = objects.GetEnumeratedType(); // BEWARE: object 
42
23 сент. atsakymą pateikė 3dGrabber 23 rugsėjis 2012-09-23 13:05 '12, 13:05 2012-09-23 13:05

Pabandykite

 list.GetType().GetGenericArguments() 
29
17 февр. Rauhotz pateikė atsakymą vasario 17 d. 2009-02-17 18:26 '09, 06:26 pm 2009-02-17 18:26

Jis veikia man. Kai myList yra tam tikras sąmonės sąrašo vaizdas.

 IEnumerable myEnum = myList as IEnumerable; Type entryType = myEnum.AsQueryable().ElementType; 
13
18 мая '11 в 13:01 2011-05-18 13:01 atsakymą pateikė Carlos Rodriguez , gegužės 18 d. 11 val. 13:01 2011-05-18 13:01

Apsvarstykite tai: aš naudoju jį 20 spausdintų sąrašų eksportui tokiu pačiu būdu:

 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); } } 
9
29 марта '10 в 22:36 2010-03-29 22:36 atsakymą pateikė Ferencas Mucsi kovo 10 d. 10 val. 10:36 2010-03-29 22:36

Jei jums nereikia viso tipo kintamojo ir tiesiog norite patikrinti tipą, galite lengvai sukurti laikiną kintamąjį ir naudoti operatorių.

 T checkType = default(T); if (checkType is MyClass) {} 
9
08 мая '15 в 13:21 2015-05-08 13:21 Sebi atsakymą pateikė gegužės 08-15 dienomis 13:21 2015-05-08 13:21

Tai galite naudoti grąžinimo tipui universaliame sąraše:

 public string ListType<T>(T value) { var valueType = value.GetType().GenericTypeArguments[0].FullName; return valueType; } 
8
05 янв. atsakymą pateikė vishal kumar Saxena 05 jan. 2017-01-05 14:45 '17, 14:45 pm 2017-01-05 14:45

GetGenericArgument() metodas turi būti nustatytas pagal jūsų egzemplioriaus bazės tipą (kurio klasė yra bendroji klasė myClass<T> ). Priešingu atveju jis grąžina tipą [0]

Pavyzdys:

 Myclass<T> instance = new Myclass<T>(); Type[] listTypes = typeof(instance).BaseType.GetGenericArguments(); 
5
29 июля '10 в 17:26 2010-07-29 17:26 Thomas atsakė liepos 29 d. 10 d. 17:26 2010-07-29 17:26

Naudoju šį išplėtimo būdą, kad pasiektume kažką panašaus:

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

Jūs jį naudojate taip:

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

Tai nėra būtent tai, ko ieškote, bet tai naudinga demonstruojant metodus.

3
28 авг. Ken Smith atsakymas, pateiktas rugpjūčio 28 d. 2014-08-28 03:07 '14 at 3:07 2014-08-28 03:07

„T“ tipą galite gauti iš bet kokio tipo rinkinio, kuris įgyvendina „IEnumerable <T>“:

 public static Type GetCollectionItemType(Type collectionType) { var types = collectionType.GetInterfaces() .Where(x => x.IsGenericType  x.GetGenericTypeDefinition() == typeof(IEnumerable<>)) .ToArray(); // Only support collections that implement IEnumerable<T> once. return types.Length == 1 ? types[0].GetGenericArguments()[0] : null; } 

Atkreipkite dėmesį, kad, pavyzdžiui, ji nepalaiko kolekcijų, kurios įdiegia IEnumerable <T> du kartus, tipus.

 public class WierdCustomType : IEnumerable<int>, IEnumerable<string> { ... } 

Darau prielaidą, kad galite grąžinti tipų tipą, jei reikia palaikyti šį ...

Be to, taip pat galite išsaugoti rezultatą pagal kolekcijos tipą, jei tai darote daug (pvz., Kilpa).

3
16 апр. Atsakyti Dan Malcolm balandžio 16 d 2014-04-16 18:31 '14 at 18:31 2014-04-16 18:31

Naudojant 3dGrabber sprendimą:

 public static T GetEnumeratedType<T>(this IEnumerable<T> _) { return default(T); } //and now var list = new Dictionary<string, int>(); var stronglyTypedVar = list.GetEnumeratedType(); 
1
03 июня '15 в 17:41 2015-06-03 17:41 atsakymas pateikiamas fantazijos birželio 03 d. 15 val. 17:41 2015-06-03 17:41
 public bool IsCollection<T>(T value){ var valueType = value.GetType(); return valueType.IsArray() || typeof(IEnumerable<object>).IsAssignableFrom(valueType) || typeof(IEnumerable<T>).IsAssignableFrom(valuetype); } 
0
05 мая '15 в 21:23 2015-05-05 21:23 Atsakymą pateikė Karanvir Kang gegužės 15 d. 15 val. 21:23 2015-05-05 21:23

Jei norite sužinoti pagrindinės nuosavybės tipą, pabandykite atlikti šiuos veiksmus:

 propInfo.PropertyType.UnderlyingSystemType.GenericTypeArguments[0] 
0
13 окт. Fatih Çelik atsakymas, spalio 13 d 2016-10-13 14:38 '16 at 14:38 pm 2016-10-13 14:38

Taip aš tai padariau

 internal static Type GetElementType(this Type type) { //use type.GenericTypeArguments if exist if (type.GenericTypeArguments.Any()) return type.GenericTypeArguments.First(); return type.GetRuntimeProperty("Item").PropertyType); } 

Tada pavadinkite jį taip

 var item = Activator.CreateInstance(iListType.GetElementType()); 

Or

 var item = Activator.CreateInstance(Bar.GetType().GetElementType()); 
0
28 июня '17 в 0:40 2017-06-28 00:40 atsakymą pateikė „ Alen.Toma“ birželio 28 d., 17 val. 0:40 2017-06-28 00:40

Tipas:

 type = list.AsEnumerable().SingleOrDefault().GetType(); 
-9
07 марта '10 в 15:12 2010-03-07 15:12 atsakymą pateikė Ferencas Mucsi, kovo 07 '10, 15:12 2010-03-07 15:12

Kiti klausimai apie žymes arba Užduoti klausimą