扩展方法&泛型的变化
来源:互联网 发布:军事小说 知乎 编辑:程序博客网 时间: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"); } }
静态类注意事项
- 不能创建对象,类似抽像类
- 不能被继承,类似sealed;
- 不能声明非静态字段
可选实参和命名实参
- 可选实参
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); }}
这部分内容的使用频率不高,如果觉得有用的话就顶一下。如果有错误的地方,就请多指教。谢谢
阅读全文
0 0
- 扩展方法&泛型的变化
- 扩展泛型方法
- 监听SharedPreference变化的方法
- Java 方法参数的变化
- 扩展阅读 四种类型的知识与时空变化观念
- Type对象获得泛型类型的两个扩展方法
- 关于如何监听div大小的变化,jquery扩展函数
- 扩展方法的使用
- C#的扩展方法
- 扩展方法的理解
- CodeIgniter的扩展方法
- c#的扩展方法
- Sort方法的扩展
- C#的扩展方法
- validate的扩展方法
- swap扩展的方法
- 扩展方法的使用
- 字符串方法的扩展
- Java的Scanner中next()、nextLine()的区别
- 1055. The World's Richest (25)
- 模型数据降序排列(快排)
- ssh-agent使用
- linux上安装mysql(rpm)
- 扩展方法&泛型的变化
- SqlMapConfig.xml文件配置 mybatis
- 内核层监控进程 线程 创建和销毁
- Selenium IDE使用的相关功能
- 【状态压缩dp 入门】POJ
- 模型数据升序排列(快排)
- web测试方法总结
- 第二章 重构原则
- 浅析Class类(反射机制原理)