扩展方法&泛型的变化

来源:互联网 发布:军事小说 知乎 编辑:程序博客网 时间:2024/06/03 09:33

扩展方方法

在不改动已经创建的类的基础上给Person类添加一个print()方法,这时就要用到扩展方法  只能在非嵌套非泛型的类中定义扩展方法
    //实现扩展方法的类必须是静态类        public static class PersonExtern    {        //扩展方法中至少有一个参数,这个参数前要加this,this后边是要扩展的类对象        //必须使用this        public static void print(this Person p)        {            Console.WriteLine("name:{0},age:{1}", p.Name, p.Age);        }    }
不止可以给自定义的类实现扩展方法,也可以为系统提供的类实现扩展方法.第一个参数是扩展到类的对象,从第二个参数开始就扩展方法的参数。不同的封闭泛型有自己的静态成员,所以不同的封闭泛型有自己的扩展方法。
public static int sum(this List<int> l,int n){    int s=0;    for(int i=0;i<n;i++)    {        s+=l[i];    }    return s;}Person p=new Person();p.print();//对象在调用方法时,首先在该类中查找方法,没找到就在当前命名空间中查找扩展方法,如果当前命名空间下没有,再去其他命名空间下查找
//扩展方法也可以重载,在调用时根据参数选择调用不同的扩展方法如果参数也一样,则只能存在于不同的命名空间中public static class PersonExtend{    public static void print(this Person p)    {        Console.WriteLine("i am the extend");    }    public static void print(this Person p,string s)    {        Console.WriteLine("i am thi extend");    }}class Program    {        public static void Main()        {            Person p = new Person();            p = null;            p.print();//空引用可以调用扩展方法,但是不能调用实例方法            p.print("ren");            //p.show();            Student s = new Student();            s.print();        }    }    public class Person    {        public Person()        {        }        public  void show()        {        }    }    public static class PersonExten    {        public static void print(this Person s)        {            Console.WriteLine("i am the exten ");        }        public static void print(this Person s,string str)        {            Console.WriteLine("i am the exten" + str);        }    }    public class Student:Person    {        public void show()        {        }    }    所以如果给object 类添加一个方法则所有的类都能调用到该方法 但是不要这样使用    public static class ObjectExten    {        public static void fun(this object o)        {            Console.WriteLine("objectExtern");        }    }

静态类注意事项

  1. 不能创建对象,类似抽像类
  2. 不能被继承,类似sealed;
  3. 不能声明非静态字段

可选实参和命名实参

  • 可选实参
    class Program    {        public static void Main()        {            int m=add(9, 1);            Console.WriteLine(m);            int n = add();//不给add()传参就计算两个默认值的和            Console.WriteLine(n);            int x = add2(100);//两个形参都有默认值,只传一个参数会赋值给第一个参数            Console.WriteLine(x);        }        //声明形参时,给形参添加默认值,调用函数时就可以不传参数,直接使用默认值进行运算        //不传参就使用默认值计算,传参就使用实参计算        public static int add(int x=10,int y=9)        {            return x + y;        }        public static int add2(int x,int y=9)//可选实参必须放在最后边        {            return x+y;        }    }
  • 命名实参
        public static void Main()        {            //命名实参,指定实参给哪个可选形参赋值            int b = add(b: 1);/通过这个形式给第二个参数传参,只能进行指定传参            Console.WriteLine(b);        }        //数组不能为可选形参  ref或out不能为可选形参        public static int add(int a=10,int b=20)        {            return a + b;        }        private string name;        public Person(string _name="defaultname")//这样也算是一个无参数的构造函数,因为你可以选择不传参数,使用默认值        {        }    public class Student:Person    {        //子类中不显示调用父类构造函数时,会自动调用父类无参的构造函数(或带参的构造函数参数有默认值)    }

泛型的 协变 、逆变

  • 协变 泛型参数从子类类型转换成父类类型。 使用out关键字

    class MainClass{    public static void Main()    {        Create<Animal> aInterface = new AnimalFactory();        Animal a = aInterface.create();        Create<Dog> dInterface = new DogFactory();        Dog d = dInterface.create();        aInterface = dInterface;//协变 泛型参数从子类到父类        Animal a2 = aInterface.create();//create返回值从子类到父类        a2.print();//调用的是dog类中的print方法        //Dog对象可以直接赋值给Animal使用,同样,泛型参数是Dog的接口也可以赋值给泛型参数是Animal的接口(泛型接口的类型转换)        //dInterface = aInterface;//逆变,泛型参数从父类到子类        //Dog d2 = dInterface.create();//create返回值是Animal对象,不能赋值给Dog引用        //泛型参数作为返回值时,只能发生协变    }}public class Animal{    public virtual void print()    {        Console.WriteLine("animal");    }}public class Dog : Animal{    public override void print()    {        Console.WriteLine("Dog");    }}public interface Create<out T>{    T create();}public class AnimalFactory : Create<Animal>{    public Animal create()    {        return new Animal();    }}public class DogFactory : Create<Dog>{    public Dog create()    {        return new Dog();    }}}
  • 逆变 必须使用in关键字
    泛型参数从父类对象转换成子类类型

    class MainClass{    public static void Main()    {        Animal a = new Animal();        Dog d = new Dog();        Show<Animal> aInterface = new ShowAniaml();        Show<Dog> dInterface = new ShowDog();        aInterface.show(a);        dInterface.show(d);        dInterface = aInterface;//逆变,泛型参数从父类到子类        dInterface.show(d);//已经将aInerface赋值给dInterface,所以调用的是aInterface的create方法,参数d从子类到父类: show方法的参数是Animal类型,Animal x = d;但是实际调用的是dog类重点print()方法。这点又回归到了多态        //aInterface = dInterface;//协变,泛型参数从子类到父类        //aInterface.show(a);//参数a从父类到子类:show方法的参数是Dog类型,Dog x = a;        //泛型参数做参数时,不能协变        //泛型的协变逆变,指泛型参数(泛型接口或泛型委托中的泛型参数)的协变逆变    }}public class Animal{    public virtual void print()    {        Console.WriteLine("Animal");    }}public class Dog : Animal{    public override void print()    {        Console.WriteLine("Dog");    }}public interface Show<in T>{    void show(T x);}public class ShowAniaml : Show<Animal>{    public void show(Animal x)    {        x.print();    }}public class ShowDog : Show<Dog>{    public void show(Dog x)    {        x.print();    }}}

    总之还是遵循:父类对象可以指向子类对象,子类对象不能指向父类对象。
    还有泛型的协变逆变,指泛型参数(泛型接口或泛型委托中的泛型参数)的协变逆变

    动态类型

    使用dynamic关键字 只有在程序执行过程中才能确定类型
    与隐式类型不同 隐式类型在编译时就能根据值推断出类型。

    class Program{    public delegate int MyDelegat(int x);    public static void Main()    {        dynamic o = new ExpandoObject();        o.Name="zhang";        o.Age = 24;        o.Addmethod = (MyDelegat)(x => x + 1);        Console.WriteLine(o.Name + o.Age);    }}

这部分内容的使用频率不高,如果觉得有用的话就顶一下。如果有错误的地方,就请多指教。谢谢

原创粉丝点击