C# GetType与typeof
在反射和泛型中经常会使用到Type类,获取Type的最常用的方法是 obj.GetType(),和typeof(T)。在获取泛型的type时有些小坑。
1 public static void Main(string[] args) 2 { 3 A a = new B 4 { 5 a = "a", 6 b = "b", 7 c = "c", 8 }; 9 B c = new B 10 { 11 a = "a", 12 b = "b", 13 c = "c", 14 }; 15 put(a); 16 put<A>(c); 17 put<B>(c); 18 put<IC>(c); 19 Console.ReadLine(); 20 } 21 public static void put<T>(T t) 22 { 23 24 Type type1 = typeof(T); 25 Console.WriteLine(); 26 Console.WriteLine("****************typeof*******************************"); 27 foreach (var item in type1.GetProperties()) 28 { 29 string name = item.Name; 30 string value = item.GetValue(t).ToString(); 31 Console.WriteLine("name=" + name + ",value=" + value); 32 } 33 Console.WriteLine("****************GetType*******************************"); 34 Type type2 = t.GetType(); 35 36 foreach (var item in type2.GetProperties()) 37 { 38 string name = item.Name; 39 string value = item.GetValue(t).ToString(); 40 Console.WriteLine("name=" + name + ",value=" + value); 41 } 42 43 } 44 45 public class A 46 { 47 public string a { get; set; } 48 } 49 public interface IC 50 { 51 string c { get; set; } 52 } 53 public class B : A,IC 54 { 55 public string c { get; set; } 56 public string b { get; set; } 57 }
在看看代码的执行结果:
发现一个问题 GetType 和typeof的结果不一样。put<T>(T t) 显而易见,在传入相同的对象不同泛型 t.GetType()的返回值是确定的,而typeof(T)是可以变化的。obj.GetType()和定义obj的类型没有直接的关系,它的返回值是 YYYY obj = new XXXX() ; XXXX的类型,不一定是YYYY的类型。typeof就不用多说了
所以在此处代码应该写typeof(T),而不是t.GetType(),不然就失去泛型的意思。
GetType()有什么妙用的,我们来看下一段代码:
1 public static void Main(string[] args) 2 { 3 D d = new D 4 { 5 a = "a", 6 b = 1, 7 d1 = new D1 { d1 = 1 }, 8 time = DateTime.Now, 9 }; 10 put2(d); 11 Console.ReadLine(); 12 } 13 public static void put2<T>(T t) 14 { 15 Type type1 = typeof(T); 16 Console.WriteLine(); 17 PropertyInfo[] Properties = type1.GetProperties(); 18 19 foreach (PropertyInfo item in Properties) 20 { 21 Console.WriteLine(item.GetType().FullName); 22 string name = item.Name; 23 object value = item.GetValue(t); 24 25 Console.WriteLine("参数的命名空间为:" +value.GetType().FullName); 26 Console.WriteLine("name=" + name + ",value=" + value.ToString()); 27 } 28 } 29 public class D 30 { 31 public string a { get; set; } 32 public int b { get; set; } 33 public DateTime time { get; set; } 34 private string c { get; set; } 35 public D1 d1 { get; set; } 36 37 } 38 public class D1 39 { 40 public int d1 { get; set; } 41 public override string ToString() 42 { 43 return d1.ToString(); 44 } 45 }
这段代码输出为:
这段代码的21行是输出item的命名空间,结果却是RuntimePropertyInfio不是定义的PropertyInfio。并且RuntimePropertyInfio这个类是不可以访问的。简单的推测出RuntimePropertyInfio 类的修饰词可能是private或者是internal,而且这个类是继承了PropertyInfio,同时也能推测出继承PropertyInfio的类绝对不是这一种。这个是c#源码中常用的一些手段。
再来看item.getValue(t)中 在源码中的返回值是object,
而我们却而已通过GetType() 获得类具体的命名空间,通过这些方法就可以处理不用的参数。