一、递归
递归是经常在企业笔试中考到的问题,也是一种特殊的执行程序,它是用方法调用自身的形式实现的,让程序代码循环执行。
说白了,就是自己调用自己。类似while(True){}的循环语句,并且语句中如果没有判断中断语句的话,就会陷入死循环,十分耗资源也不利。
例
创建一个递归函数,也是成员方法。
public int digui(int n){ if(n==0){ return 1; } int a = n*digui(n - 1); return a;}
这是一个计算n的乘阶的递归,自己乘以自己-1;
如果没有if语句的话,你会发现,根本就停不下来,也不会有结果。
而return在程序中也起到中断跳出程序的效果。
1.例
使用递归实现计算所输入数的阶乘。
如计算 5 的阶乘,则是 5*4*3*2*1 的结果。
实现的代码如下。
class FactorialClass{ public static int Factorial(int n) { if(n == 0) { return 1; } return n * Factorial(n - 1); }}
在 Main 方法中调用该静态方法,代码如下。
class Program{ static void Main(string[] args) { int rs = FactorialClass.Factorial(5); Console.WriteLine("结果是:" + rs); }}
分析:
首先是定义的类,这里用的是静态static,目的是不用声明类的对象,直接使用。
然后是递归函数,当参数为0时,返回一个1.
这是输入的是5,所以先将5放进递归中。
也就是5*Factorial(4);
等于5*4 * Factorial(3);
5*4*3 * Factorial(2);
5*4*3*2 * Factorial(1);
5*4*3*2*1*Factorial(0);
因为Factorial(0)==1,所以5*4*3*2*1*1 == 120.
结果也就是120.
如果使用for循环进行编辑
int rs=l; //存放阶乘的结果for(int i=1; i<=n;i++){ rs = rs*i;}
分析:
rs是最终结果。
n是阶乘数。
然后循环计算。
二、嵌套类
在类中除了能编写前面提到的类成员以外,还能直接定义类。
将一个类定义在另一个类的内部,即可将在类内部定义的类称为嵌套类。
也就是类中类。模块套模块。
在 C# 中嵌套类相当于类中的成员,能使用类成员的访问修饰符和修饰符。
但是,在访问嵌套类中的成员时必须加上外层类的名称。
例:
class A{ class B{ public int num=1; }}//调用A.B n = new A.B();Console.WriteLine(n.num);
1.例
定义名为 OuterClass 的类,在其中定义名为 InnerClass 的类,并在类中定义两个属性,即卡号和密码,而且定义方法输出属性的值。
class OuterClass{ public class InnerClass { public string CardId { get; set; } public string Password { get; set; } public void PrintMsg() { Console.WriteLine("卡号为:" + CardId); Console.WriteLine("密码为:" + Password); } }}
在 Main 方法中调用嵌套类的成员,代码如下。
class Program{ static void Main(string[] args) { OuterClass.InnerClass outInner = new OuterClass.InnerClass(); outInner.CardId = "622211100"; outInner.Password = "123456"; outInner.PrintMsg(); }}
分析:
创建了一个嵌套类,剩下的就是定义变量和方法。
变量采用的了访问器简写形式。
使用时,在声明时需要把外面的类也带上。
如上面的第5行。
三、部分类
正如字面上的意思,它用于表示一个类中的一部分。
一个类可以由多个部分类构成,定义部分类的语法形式 如下。
访问修饰符 修饰符 partial class 类名{……}
在这里,partial 即为定义部分类的关键字。
部分类主要用于当一个类中的内容较多时将相似类中的内容拆分到不同的类中,并且部分类的名称必须相同。
例
public partial class A{ public int a { get; set; }}public partial class A{ public void P() { Console.WriteLine(a); }}
算是将两段相同名字的类,拼合起来。
1.例
定义名为 Course 的类,分别使用两个部分类实现定义课程属性并输出的操作。在一个部分类中设定课程的属性,在一个部分类中定义方法输出课程的属性。
public partial class Course{ public int Id { get; set; } public string Name { get; set; } public double Points { get; set; }}public partial class Course{ public void PrintCoures() { Console.WriteLine("课程编号:" + Id); Console.WriteLine("课程名称:" + Name); Console.WriteLine("课程学分:" + Points); }}
在 Main 方法中为属性赋值并调用 PrintCourse 方法,代码如下。
static void Main(string[] args){ Course course = new Course(); course.Id = 1001; course.Name = "C#部分类"; course.Points = 3; course.PrintCoures();}
分析,类的定义就是两段拼接的。
然后跟正常那样进行使用。
从该实例可以看出,在不同的部分类中可以直接互相访问其成员,相当于所有的代码都写到一个类中。
此外,在访问类成员时也非常方便,直接通过类的对象即可访问不同部分类的成员。
除了定义部分类外,还可以在部分类中定义部分方法,实现的方式是在一个部分类中定义一个没有方法体的方法,在另一个部分类中完成方法体的内容。
四、部分方法
部分方法用的不是特别多,这里咱们了解即可。
使用部分方法需要注意如下 3 点:
部分方法必须是私有的,并且不能使用 virtual、abstract、override、new、sealed、extern 等修饰符。
部分方法不能有返回值。
在部分方法中不能使用 out 类型的参数。
1.例
在实例 1 的基础上添加部分方法,在第一个部分类中添加一个没有方法体的 PrintCourse 方法。
public partial class Course{ public int Id { get; set; } public string Name { get; set; } public double Points { get; set; } partial void PrintCourse(); //调用PrintCourse方法 public void PrintMsg() { PrintCourse(); }}public partial class Course{ public void PrintCoures() { Console.WriteLine("课程编号:" + Id); Console.WriteLine("课程名称:" + Name); Console.WriteLine("课程学分:" + Points); }}
由于部分方法是私有的,因此在 Course 类中添加一个打印方法 PrintMsg 来调用 PrintCourse 方法,以方便在其他类中调用。
在 Main 方法中调用 PrintMsg 方法的代码如下。
static void Main(string[] args){ Course course = new Course(); course.Id = 1001; course.Name = "C#部分类"; course.Points = 3; course.PrintMsg();}
实际上,都是相同的类或方法,被拆成了两段。
其实际情况却是,为了补充之前的类或方法,却找不到放哪了,就可以再声明一个进行补充。
方法之所以不常用,其实也是不好确定在哪个类中。
反而类是一大块一大块的,所以比较好找吧!
五、Console类:控制台输入输出
主要用于控制台应用程序的输入和输岀操作。
其实就是经常用的输出和输入的语句。
Console.WriteLine("");
方法 | 描述 |
---|---|
Write | 向控制台输出内容后不换行 |
WriteLine | 向控制台输出内容后换行 |
Read | 从控制台上读取一个字符 |
ReadLine | 从控制台上读取一行字符 |
此外,在向控制台中输出内容时也可以对输出的内容进行格式化,格式化时使用的是占位符的方法,语法形式如下。
Console.Write(格式化字符串, 输出项, 输出项2);
其中,在格式化字符串中使用{索引号}的形式,索引号从 0 开始。输出项 1 填充 {0} 位置的内容,依此类推。
1.例
从控制台依次输入姓名和所在学校,并在输出时组成一句话“xx 同学在 xx 学习”。
class Program{ static void Main(string[] args) { Console.WriteLine("请输入学生姓名:"); string name = Console.ReadLine(); Console.WriteLine("请输入所在学校:"); string school = Console.ReadLine(); Console.WriteLine("{0}同学在{1}学习", name, school); }}
六、Math类
主要用于一些与数学相关的计算,并提供了很多静态方法方便访问,常用的方法如下表所示。
就是数学公式,变成了方法函数。
方法 | 描述 |
---|---|
Abs | 取绝对值 |
Ceiling | 返回大于或等于指定的双精度浮点数的最小整数值 |
Floor | 返回小于或等于指定的双精度浮点数的最大整数值 |
Equals | 返回指定的对象实例是否相等 |
Max | 返回两个数中较大数的值 |
Min | 返回两个数中较小数的值 |
Sqrt | 返回指定数字的平方根 |
Round | 返回四舍五入后的值 |
1.例
从控制台输入两个数,分别使用 Max 和 Min 方法输出其中的最大值和最小值。
class Program{ static void Main(string[] args) { Console.WriteLine("请输入第一个数:"); double num1 = Double.Parse(Console.ReadLine()); Console.WriteLine("请输入第二个数:"); double num2 = Double.Parse(Console.ReadLine()); Console.WriteLine("两个数中较大的数为{0}", Math.Max(num1, num2)); Console.WriteLine("两个数中较小的数为{0}", Math.Min(num1, num2)); }}
通过 Math 类中的 Max 和 Min 方法很容易实现获取两个数中最大值和最小值的操作。
也就是将进行if判断的具体代码封装在了Max和Min方法中,在放进了Math类中。
然后进行类的调用,也就是所谓的造轮子。
七、Random类
是一个产生伪随机数字的类,它的构造函数有两种。
例:
New Random();New Random(Int32)。
总之就是由机器生成的随机数字,但却并不是真的随机数字。
因此如果计算机运行速度很快,如果触发 Randm 函数间隔时间很短,就有可能造成产生一样的随机数,因为伪随机的数字,在 Random 的内部产生机制中还是有一定规律的,并非是真正意义上的完全随机。
Random 类中提供的 Next、NextBytes 以及 NextDouble 方法可以生成整数类型、byte 数组类型以及双精度浮点型的随机数,详细说明如下表所示。
方法 | 描述 |
---|---|
Next() | 每次产生一个不同的随机正整数 |
Next(int max Value) | 产生一个比 max Value 小的正整数 |
Next(int min Value,int max Value) | 产生一个 minValue~maxValue 的正整数,但不包含 maxValue |
NextDouble() | 产生一个0.0~1.0的浮点数 |
NextBytes(byte[] buffer) | 用随机数填充指定字节数的数组 |
1.例
分别使用 Next、NextDouble 以及 NextBytes 方法生成随机数。
class Program{ static void Main(string[] args) { Random rd = new Random(); Console.WriteLine("产生一个10以内的数:{0}", rd.Next(0, 10)); Console.WriteLine("产生一个0到1之间的浮点数:{0}", rd.NextDouble()); byte[] b = new byte[5]; rd.NextBytes(b); Console.WriteLine("产生的byte类型的值为:"); foreach(byte i in b) { Console.Write(i + " "); } Console.WriteLine(); }}
分析
声明一个随机数Random对象,然后通过类中的方法进行使用。
八、DateTime类
用于表示时间,所表示的范围是从 0001 年 1 月 1 日 0 点到 9999 年 12 月 31 日 24 点。
在 DateTime 类中提供了静态属性 Now,用于获取当前的日期和时间。
表达形式
DateTime.Now
DateTime 类提供了 12 个构造方法来创建该类的实例,但经常使用不带参数的方法创建 DateTime 类的实例。
在 DateTime 类中提供了常用的属性和方 法用于获取或设置日期和时间,如下表所示。
方法 | 描述 |
---|---|
Date | 获取实例的日期部分 |
Day | 获取该实例所表示的日期是一个月的第几天 |
DayOfWeek | 获取该实例所表示的日期是一周的星期几 |
DayOfYear | 获取该实例所表示的日期是一年的第几天 |
Add(Timespan value) | 在指定的日期实例上添加时间间隔值 value |
AddDays(double value) | 在指定的日期实例上添加指定天数 value |
AddHours(double value) | 在指定的日期实例上添加指定的小时数 value |
AddMinutes(double value) | 在指定的日期实例上添加指定的分钟数 value |
AddSeconds(double value) | 在指定的日期实例上添加指定的秒数 value |
AddMonths(int value) | 在指定的日期实例上添加指定的月份 value |
AddYears (int value) | 在指定的日期实例上添加指定的年份 value |
1.例
使用 DateTime 类获取当前时间,分别输出该日是当月的第几天、星期几以 及一年中的第几天,并计算 30 天后的日期。
class Program{ static void Main(string[] args) { DateTime dt = DateTime.Now; Console.WriteLine("当前日期为:{0}", dt); Console.WriteLine("当前时本月的第{0}天", dt.Day); Console.WriteLine("当前是:{0}", dt.DayOfWeek); Console.WriteLine("当前是本年度第{0}天", dt.DayOfYear); Console.WriteLine("30 天后的日期是{0}", dt.AddDays(30)); }}
同样,先定义,然后再调用里面的方法。
至于具体情况,因为都封装了,所以会感觉没有实感。
在使用 DateTime 类中的 Add 方法时需要使用时间间隔类 TimeSpan,该类允许表示的时间间隔范围是 0 到 64 位整数。
两个日期的差可由时间间隔类 TimeSpan 的对象来存放。假设计算现在距离2021年6月1日儿童节的天数,代码如下。
class Program{ static void Main(string[] args) { DateTime dt1 = DateTime.Now; DateTime dt2 = new DateTime(2021, 6, 1); TimeSpan ts = dt2 - dt1; Console.WriteLine("间隔的天数为{0}天", ts.Days); }}
分析:
首先获取当前时间dt1;
然后获取要设定的时间;
再进行相减。
再通过.Days将其转变成天数。