首先看一段测试代码,自己写的
class Program
{
static void Main(string[] args)
{
man OneMan = new man();
var d = OneMan.CreatNewObject() as man ; // 这里是父类object转换为子类man,逆变
Console.WriteLine("这是OneMan的类 "+OneMan); // 打印对象,默认打印对象的toString方法
d.Speak();
Console.ReadKey();
}
}
public class man
{
public object CreatNewObject() // 这里是子类变为object父类,是协变
{
son g = new son();
return g;
}
public override string ToString() // 覆写ToString方法后
{
string result = "I的值为{0},A为";
return result;
}
public void Speak()
{
Console.WriteLine("this is a too much top!");
}
}
public class son: man
{
}
测试结果
1.逆变和协变的条件是两者存在继承关系(或者说两者间有直线),两个不同的类是无法逆变或者协变的
2.直接打印类默认调用的是类的ToString方法,如果类没有重写ToString方法,默认调用的就是object的ToString方法
in 参数 : 表示参数可能会逆变
out 参数 : 表示参数可能会协变
一个比较好的实例
// 第一种通过as转换类型来调用类中的方法
var a1 = GetAnimal() as Animal;
a1.Speak();
// 第二种是通过反射将object中的方法调出来
a1.GetType().GetMethod("Speak").Invoke(a1, null);
// 第三种调用方法是通过dynamic关键字,在运行时将object转换为Animal类,直接调用类中的方法
dynamic a2 = GetAnimal();
a2.Speak(); // 注意,这个dynamic是没有智能提示的,要把字母全部输出正确才行
Type aa = Assembly.Load("dogs").GetType("dogs.Class1"); // dogs是namespace名称,Class1是类名,GetType方法可以直接从命名空间下的类名取得该类的Type类型/属性
dynamic bb = Activator.CreateInstance(aa);
bb.Voice(); // Voice()是类中的方法
a1.age.a = "jingya";
a1.age.b = 23;
Console.WriteLine(a1.age.a);
Console.ReadKey();
}
static object GetAnimal() // c#中的很多返回值都是object,通过反射才能调用其中的方法,反射太麻烦了,不如用dynamic简单,也没有dynamic性能高
{
return new Animal() { name = "xiaolizi Animal " };
}
}
public class Animal
{
public dynamic age { get; set; }
public string name = "a ben mao ";
public void Speak()
{
Console.WriteLine("this is a Animal Speak voice");
}