C#-逆变 协变 反射 代码

时间:2022-07-22 07:54:09

首先看一段测试代码,自己写的

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. man OneMan = new man();
  6. var d = OneMan.CreatNewObject() as man ; // 这里是父类object转换为子类man,逆变
  7. Console.WriteLine("这是OneMan的类 "+OneMan); // 打印对象,默认打印对象的toString方法
  8. d.Speak();
  9. Console.ReadKey();
  10. }
  11. }
  12. public class man
  13. {
  14. public object CreatNewObject() // 这里是子类变为object父类,是协变
  15. {
  16. son g = new son();
  17. return g;
  18. }
  19. public override string ToString() // 覆写ToString方法后
  20. {
  21. string result = "I的值为{0},A为";
  22. return result;
  23. }
  24. public void Speak()
  25. {
  26. Console.WriteLine("this is a too much top!");
  27. }
  28. }
  29. public class son: man
  30. {
  31. }

测试结果
1.逆变和协变的条件是两者存在继承关系(或者说两者间有直线),两个不同的类是无法逆变或者协变的
2.直接打印类默认调用的是类的ToString方法,如果类没有重写ToString方法,默认调用的就是object的ToString方法

in 参数      : 表示参数可能会逆变
out 参数    : 表示参数可能会协变

一个比较好的实例
  1. // 第一种通过as转换类型来调用类中的方法
  2. var a1 = GetAnimal() as Animal;
  3. a1.Speak();
  4. // 第二种是通过反射将object中的方法调出来
  5. a1.GetType().GetMethod("Speak").Invoke(a1, null);
  6. // 第三种调用方法是通过dynamic关键字,在运行时将object转换为Animal类,直接调用类中的方法
  7. dynamic a2 = GetAnimal();
  8. a2.Speak(); // 注意,这个dynamic是没有智能提示的,要把字母全部输出正确才行
  9. Type aa = Assembly.Load("dogs").GetType("dogs.Class1"); // dogs是namespace名称,Class1是类名,GetType方法可以直接从命名空间下的类名取得该类的Type类型/属性
  10. dynamic bb = Activator.CreateInstance(aa);
  11. bb.Voice(); // Voice()是类中的方法
  12. a1.age.a = "jingya";
  13. a1.age.b = 23;
  14. Console.WriteLine(a1.age.a);
  15. Console.ReadKey();
  16. }
  17. static object GetAnimal() // c#中的很多返回值都是object,通过反射才能调用其中的方法,反射太麻烦了,不如用dynamic简单,也没有dynamic性能高
  18. {
  19. return new Animal() { name = "xiaolizi Animal " };
  20. }
  21. }
  22. public class Animal
  23. {
  24. public dynamic age { get; set; }
  25. public string name = "a ben mao ";
  26. public void Speak()
  27. {
  28. Console.WriteLine("this is a Animal Speak voice");
  29. }