1.静态变量和静态函数
静态函数和静态变量只能通过类名来调用,不能通过实例名来调用
静态函数里调用其他函数,该函数也应该是静态的
对于静态函数和静态变量来说,不同实例里面,其是相同的,共享一个
static void Main(string[] args)
{
Console.WriteLine(Sample.bStatic);
Sample s = new Sample() ;
Console.WriteLine("Frist Time");
Console.WriteLine(Sample.bStatic);
s.a++;//只能调用非静态
//Sample.bStatic++;//静态只能通过类名调用,不能通过实例来调用,所有实例共享一个静态
// Sample.StaticSample();
// Console.WriteLine(Sample.bStatic);
//Console.WriteLine(Sample.bStatic++);//先使用,再加一
//Console.WriteLine(Sample.bStatic);
Sample s1 = new Sample();
Console.WriteLine("Second Time");
Console.WriteLine(Sample.bStatic);
Sample s2 = new Sample();
Console.WriteLine("Third Time");
Console.WriteLine(Sample.bStatic);
}
}
class Sample
{
public int a = 0;
public static int bStatic=0;
public static void StaticSample()
{
Console.WriteLine("This is static method.");
}
public Sample() //在内部可以直接调用静态变量
{
bStatic++;//没创建一个实例就加1
}
2.值类型的值传递和引用传递
值传递在不同函数中,虽然变量命名可能相同,但是会分配不同的空间,只是会拷贝一份给函数当作实参,所以在不同函数中,其值没有办法传递;
引用传递是,不会为方法参数列表里的参数再分配空间;
引用类型:变量名字里储存的是索引(句柄)
static void Main(string[] args)
{
int a = 99;
int b = 10;
Console.WriteLine("原始值");
Console.WriteLine("a={0}&&b={1}", a, b);
Swap1(a, b);
Console.WriteLine("使用Swap1");
Console.WriteLine("a={0}&&b={1}", a, b);
Swap2(ref a, ref b);
Console.WriteLine("使用Swap2");
Console.WriteLine("a={0}&&b={1}", a, b);
}
static void Swap1(int a,int b)//值传递,为参数列表重新分配空间
{
int temp = a;
a = b;
b = temp;
}
static void Swap2(ref int a,ref int b) //引用传递,不为参数列表分配空间
{
int temp = a;
a = b;
b = temp;
}
3.引用类型的参数传递
引用类型是指名字中存储的是句柄,而不是数据。以数组为参数,就是一种引用类型的值传递
以数组为参数的值传递,但其传递的是位置信息,所以也可以直接在原空间中改变数据
引用传递 ref a 表示a是标记着内存一块区域的标记,调用时,不会拷贝一份给函数当作实参,调用函数中使用的新的标记就是原来的标记,共用一个标记
对于引用参数来说,无论是拷贝了一份标记,还是两个标记就是同一个,其能起到的作用是一样的,所以其值传递和引用传递起到的效果是一样的,在调用结束后,其原函数中的值都会发生改变
但是在引用传递中,如果在函数中重新分配一个空间,让标记值向新的空间,函数结束,标记销毁,无法指回原来的空间,还留在新空间;在值传递中,由于标记是拷贝的,虽然会重新分配空间让标记指向新空间,但是函数结束后,还是会指向原来的空间。
static void Main(string[] args)
{
int[] a = { 1, 2, 3 };
Console.WriteLine("初始值");
foreach (int i in a )
Console.Write("{0} ", i);
Console.WriteLine("*****");
//Console.WriteLine("调用Add1");
//Add1(a);
//foreach (int i in a)
// Console.Write("{0} ", i);
//Console.WriteLine("*****");
Console.WriteLine("调用Add2");
Add2(ref a);
foreach (int i in a)
Console.Write("{0} ", i);
Console.WriteLine("*****");
Console.WriteLine("调用Add1");
Add1(a);
foreach (int i in a)
Console.Write("{0} ", i);
Console.WriteLine("*****");
//Console.WriteLine("调用Add3");
//Add3(ref a); //a是标记着内存一块区域的标记
//foreach (int i in a)
// Console.Write("{0} ", i);
//Console.WriteLine("*****");
//Console.WriteLine("调用Add4");
//Add4(a);
//foreach (int i in a)
// Console.Write("{0} ", i);
//Console.WriteLine("*****");
}
static void Add1(int []a)// 传递句柄,不用重新分配空间,调用结束后,主函数中的值已经被改变 //值传递
{
for (int i=0;i <a.Length;i++) //传递位置信息
{
a[i]++;
}
}
static void Add2(ref int[] a) //传递句柄,不用重新分配空间,调用结束后,主函数中的值已经被改变,和1一样 //引用传递
{
for (int i = 0; i < a.Length; i++)
{
a[i]++;
}
}
static void Add3(ref int[] a)//重新分配,但是不会被销毁,主函数中a的值会发生改变 //引用传递 和主函数中公用一个空间
{
a=new int[4] { 10, 11, 12 ,13}; //重新分配一个空间后,指向新的空间,但是函数运行结束后,无法指向原来的空间,丢失
for (int i = 0; i < a.Length; i++)
{
a[i]++;
}
}
static void Add4(int[] a) //重新分配空间,但是调用完后会被销毁,主函数中a的值任然不变 //值传递 将主函数中的a拷贝一份传递过来,
{
a = new int[4] { 10, 11, 12, 13 }; //重新分配一个空间后,,指向新的空间,但是函数运行结束后,标记销毁,又指回原来的空间
for (int i = 0; i < a.Length; i++)
{
a[i]++;
}
}
}
4.可选参数和命名参数、变长参数
static void Main(string[] args)
{
int a = 1;
double b = 2;
int c = 3;
char h = 'b';
Method(a, b, c, h);//可以给可选参数赋值
Method(a, b, c);//也可以不赋值,就使用默认值
Method(a, b, d: h);//命名参数:参数d的值使用之前定义的h的值 其中C是缺省的,使用默认值
Method(a, b, c: 10);
Console.WriteLine(Average(1));
Console.WriteLine(Average(1, 2, 3, 4));
}
static void Method(int a,double b,int c=1,char d='R')//其中d 为可选参数,其默认值为R 一个函数的可选参数要一起放在最后
{
a = a + 1;
b = a + 1;
}
static double Average(params int []a)//参数传递过来的数量可能是不定的,存储在数组里 其数据类型应该是一样的
{
int b = a.GetLength(0); //参数列表只能有一个不定长参数,可以加入定长参数
double sum = 0;
foreach (int k in a)
sum += k;
return sum / b;
}
5.方法的重载
//方法重载:方法名字一样,但是:参数数量不同
//参数数量相同,但参数类型不同
//参数数量和类型相同但是出现顺序不同
//函数返回值类型不能作为重载的依据
static void Main(string[] args)
{
double s = TriangleArea(3, 4, 5);
double s2 = TriangleArea(3d, 4d, 5d);
}
//方法重载:方法名字一样,但是:参数数量不同
//参数数量相同,但参数类型不同
//参数数量和类型相同但是出现顺序不同
//函数返回值类型不能作为重载的依据
static double TriangleArea(double a,double b,double c)
{
Console.WriteLine("1");
double s = (a + b + c) / 2;
return Math.Sqrt(s * (s - a) * (s - b) * (s - c));
}
static double TriangleArea(double a, double h)
{
Console.WriteLine("2");
return (a * h) / 2;
}
static double TriangleArea(int a, int b, double theta)
{
Console.WriteLine("3");
return (a * b * Math.Sin(theta)) / 2;
}
6.递归
程序中函数调用自己 每次规模减小 到最后又确定值
递归求阶乘:
static void Main(string[] args)
{
Console.WriteLine(Fac(5));
}
static int Fac(int n)
//递归求阶乘 程序中函数调用自己 每次规模减小 到最后又确定值
{
if (n == 0)
return 1;
else
return n * Fac(n - 1);
}
递归求汉诺塔:
static void Main(string[] args)
{
Hanmethod(5, 'A', 'B', 'C');
Console.WriteLine(count);
}
static int count = 0;
static void Move(char a,char c)
{
Console.WriteLine("From{0} to {1}", a, c);
count++;
}
static void Hanmethod(int n,char a,char b,char c)
{
if (n == 1)
Move(a, c);
else
{
Hanmethod(n - 1, a, c, b);
Move(a, c);
Hanmethod(n - 1, b, a, c);
}
}