在不改动已经建立的类的基础上给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");
}
}
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关键字web
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关键字
泛型参数从父类对象转换成子类类型c#
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关键字 只有在程序执行过程当中才能肯定类型
与隐式类型不一样 隐式类型在编译时就能根据值推断出类型。ide
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);
}
}