简介
第一次发博客,欢迎交流沟通。
因为学习虚拟现实需要所以暑假一个月学了点C#,做了笔记,在这进行分享,欢迎浏览。
有些代码打在VS中 没有记录在笔记里 请见谅。
(视频指路)
基础篇
1. .Net平台
-
.Net平台与.Net Framework框架
框架提供了环境和原料来保证平台的稳定运行
一道道精美的菜是基于平台制作出来的软件、应用
即框架是包含于.Net平台的
2. c#编程语言
-
不能脱离.Net Framework框架
-
能干什么?
-
.Net两种交互模式
-
VS的组成
-
解决方案—项目—类 .cs结尾的为类文件
解决方案:公司
项目:部门
类:员工
-
引用命名空间:
京东 —京东在线商城项目 — 顾客类
淘宝 —京东在线商城项目 — 顾客类
另一个公司 — 另一个项目 — 顾客类 包含了京东和淘宝两个
-
方法 / 函数
C#文件只写在函数里边
-
.sln:解决方案文件 里边包含整个解决方案的信息 可以双击运行
.csproj:项目文件 里边包含整个项目的信息 可以双击运行
-
3.代码
Console.WriteLine("Hello World");
Console.Readkey(); //严格区分大小写
//先按F6进行检查 再用F5运行
- 项目如果不想用了可以按卸载 这也不会丢失代码
4.基本语法
1.注释
单行注释 //
多行注释 /* */
文档注释 /// (用来描述类和方法 这个在方法内使用不会跳出描述)
2.常用快捷键
- 折叠冗余代码
region和文字中间要空一个空格
里边的内容也可以注释掉
3.变量存储及变量的几种类型
-
整数类型:int 只能存储整数,不能存储小数
-
小数类型:double 既能存储整数,也能存储小数,小数点后面的位数 15~16位 float存储6~9位
-
金钱类型:decimal:用来存储金钱,值后面需要加上一个 小数点后面的位数28~29位
1。与
float
和double
相比,decimal
类型具有更高的精度和更小的范围,因此它适合于财务和货币计算。2.不带后缀的文本或带有
d
或D
后缀的文本的类型为double
- 带有
f
或F
后缀的文本的类型为float
- 带有
m
或M
后缀的文本的类型为decimal
- 带有
-
字符串类型:string,用来存储多个文本,也可以存储空,字符串类型的值需要被 双引号引来
-
字符类型:char,用来存储单个字符,最多、最少只能有一个字符,不能存储空
-
bool类型:true或者false 判断对错
4.变量使用该规则
一.首先要保证的就是这个变量的名字要有意义。
1 现阶段给变量起名字的时候都以字母开头
2 后面可以跟任意“字母”、数字、下划线.
二.注意:
1)起的变量名不要与c#系统中的关键字重复.
2)在c#中,大小写是敏感的. HTML
3)同一个变量名不允许重复定义
给变量起名字的时候要满足两个命名规范:
1、Camel 骆驼命名规范。要求变量名首单词的首字母要小写,其余每个单词的首字母要大写。
多用于给变量或者字段命名。
highSchoolStudent
2、Pascal 命名规范:要求每个单词的首字母都要大写,其余字母小写。多用于给类或者方法命名。
HighSchoolStudent
5.赋值运算符
=:表示赋值的意思,表示把等号右边的值,赋值给等号左边的变量。
由等号连接的表达式称之为赋值表达式。
注意:每个表达式我们都可以求解除一个定值,对于赋值表达式而言,等号左边的变量的值,
就是整个赋值表达式的值。
int number=10;
6.+号的作用
1)、连接:当+号两边有一边是字符串的时候,+号就起到连接的作用。
2)、相加:两边是数字的时候
7.占位符的使用
-
使用方法:先挖个坑,再填个坑。
使用占位符需要注意的地方:
1、你挖了几个坑,就应该填几个坑,如果你多填了,没效果。
如果你少填了,抛异常。
2、输出顺序:按照挖坑的顺序输出。 -
异常是指:语法上并没有任何错误,只不过在程序运行的期间,由于某些原因出现了问题,
使程序不能再正常的运行
8.输入输出
Console.WriteLine("请输入您的名字:");
string name = Console.ReadLine();
Console.WriteLine("请输入您的性别:");
string sex = Console.ReadLine();
Console.WriteLine("请输入您的年龄:");
string age = Console.ReadLine();
Console.WriteLine("我叫{0},性别{1},年龄{2}", name, sex, age);
Console.ReadKey(); // 只能是string 这样可以包含任意类型
9.转义字符
- 转义符指的就是一个’’+一个特殊的字符,组成了一个具有特殊意义的字符。(注意:转完是一个字符)
\n:表示换行
":表示一个英文半角的双引号
\t:表示一个tab键的空格
\b:表示一个退格键,放到字符串的两边没有效果。
\r\n:windows操作系统不认识\n,只认识\r\n
\:表示一个\ - @符号
1、取消\在字符串中的转义作用,使其单纯的表示为一个’’
2、将字符串按照编辑的原格式输出
10.类型转换
- 隐式类型转换:我们要求等号两遍参与运算的操作数的类型必须一致,如果不一致,满足下列条件会发生自动类型转换,或者称之为隐式类型转换。
- 两种类型兼容
例如:int 和 double 兼容 (都是数字类型) - 目标类型大于源类型
例如:double > int 小的转大的 - 显示类型转换 / 强制类型转换:
1、两种类型相兼容 int–double
2、大的转成小的 double----int
语法:
(待转换的类型)要转换的值; - 输出double保留位数 Console.WriteLine("{0:0.00}",d); //保留了两位数
5.运算符
1.convert类型转换
- 类型如果相兼容的两个变量,可以使用自动类型转换或者强制类型转换
- 但是,如果两个类型的变量不兼容,比如 string与int或者string 与double,这个时候我们可以使用一个叫做Convert的转换工厂进行转换。
- 注意:使用Convert进行类型转换,也需要满足一个条件:
面儿上必须要过的去。 (即字符串“"123abc"不能转换为数值类型) - int s = Convert.Int32(要转换的变量)
2.加加减减
- ++:分为前++和后++,不管是前++还是后++,最终的结果都是给这个变量加一。
- 区别表现表达式当中,如果是前++,则先给这个变量自身加一,然后带着这个加一后的值去参与运算。
- 如果是后++,则先拿原值参与运算,运算完成后,再讲这个变量自身加一。
- –:同上
- 对于向加加或者减减这样只需要一个操作数就能完成的运算,我们称之为一元运算符。
- / % 对于这些需要两个或以上才能完成运算的操作符,我们称之为二元运算符。
- 一元运算符的优先级要高于二元运算符。
如果在一个表达式当中,既有一元运算符,又有二元运算符,我们首先计算一元运算符。
3.关系运算符
- < <= > >= == !=
- 关系运算符是用来描述两个事物之间的关系
由关系运算符连接的表达式称之为关系表达式。 - bool类型
在c#中我们用bool类型来描述对或者错。
bool类型的值只有两个 一个true 一个false
4.逻辑运算符
- && 逻辑与
- ||逻辑或
- !逻辑非
- 又逻辑运算符连接的表达式叫做逻辑表达式
5.复合赋值运算符
+= -= *+ /= %=
6.优先级
6.结构
- 顺序结构:程序从Main函数进入,从上到下一行一行的执行,不会落下任何一行。
- 分支结构:if if-else
- 选择结构:if else-if switch-case
- 循环结构:while do-while for foreach
(内容同C语言)
要记住代码最后有三个括号
输入账号和密码 没必要转换成int类型
//有两种以上情况的用if else-if
//第一种情况:用户名和密码全部输入正确
if (name == "admin" && pwd == "888888") {
Console.WriteLine("登陆成功");
}
//第二种情况:密码错误
else if (name == "admin") {
Console.WriteLine("密码输入错误,程序退出");
}
//第三种情况:用户名错误
else if (pwd == "888888") {
Console.WriteLine("用户名错误,程序退出");
}
//第四种情况:用户名和密码全部错误
else {
Console.WriteLine("用户名和密码全部错误,程序退出");
}
7.流程控制
1.异常捕获
我们在程序中经常会出现各种各样的异常,你如果想要你的程序变得坚强一些。
在你的代码中应该经常性的使用try-catch来进行异常捕获。
一般是所有代码都写完后再写try-catch来检查
哪行代码有可能出现异常,你就踹它一脚。
try
{
可能会出现异常的代码;
....
...
...
}
//try和catch之间不能有其他的代码
catch
{
出现异常后要执行的代码;
} 要注意变量的三部曲问题 有一个出错后边另一个步骤可能就运行不了 e.g 输入数值 但是可能会输入abc导致无法转化 此时就要在声明变量时赋初值为0
执行过程:如果try中的代码没有出现异常,那么catch中的代码不会执行。
如果try中的代码出现了异常,那怕这行出现异常的代码后面还有一百行都不会执行了,
而是直接跳到catch中执行代码 (类似于if-else)
- 变量的作用域:
变量的作用域就是你能够使用到这个变量的范围。
变量的作用域一般从声明它的那个括号开始到那个括号所对应的结束的括号结束。
在这个范围内,我们可以访问并使用变量。超出这个范围就访问不到了
2.switch-case
用来处理多条件的定值的判断。
if else-if 处理的是带范围的判断
switch(变量或者表达式的值)
{
case 值1:要执行的代码;
break;
case 值2:要执行的代码;
break;
case 值3:要执行的代码;
break;
..........
default:要执行的代码;
break;
}
//输出输入的月份对应的天数
Console.WriteLine("请输入年份");
try {
int year = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("请输入月份");
int month = Convert.ToInt32(Console.ReadLine());
if (month >= 1 && month <= 12) {
int day = 0;
switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
day = 31;
break;
case 2:
if ((year % 400 == 0) || (year % 100 != 0 && year % 4 == 0)) {
day = 29;
} else {
day = 28;
}
break;
default:
day = 30;
break;
}
Console.WriteLine("{0}年{1}月有{2}天", year, month, day);
}
else {
Console.WriteLine("输入的月份有错,请重新输入");
}
}
catch {
Console.WriteLine("输入的年份有错,请重新输入");
}
Console.ReadKey();
3.循环结构
while:特点:先判断,再执行,有可能一遍循环都不执行。( 同C )
4.break、continue
- 可以跳出switch-case结构。
- 可以跳出当前循环。
break一般不单独的使用,而是跟着if判断一起使用,表示,当满足某些条件的时候,就不再循环了。
//输入后不换行
Conosole.Write("\t");
Console.WriteLine(); //什么都不写也会自动换行
continue 跳出当前循环进行判断 条件符合继续循环 否则跳出循环
5.类型转换
int number = 100;
bool b = int.TryParse("123abc",out number); //把数值转换为数字并赋值给number 这里的TryPrase是一个方法 如果转换成功则b为true number为转换后的值 如果不成功则b为false 并赋值number = 0
//不同于convert.Int32和int.Prase 这两个如果转换不成功会报错
Console.WriteLine(b);
Console.WriteLine(number);
6.断点调试
调试方法:
1)F11逐语句调试(单步调试)
2)F10逐过程调试
3)断点调试
7.三元表达式
- 表达式1?表达式2:表达式3;
- 表达式1一般为一个关系表达式。
- 如果表达式1的值为true,那么表达式2的值就是整个三元表达式的值。
如果表达式1的值为false,那么表达式3的值就是整个三元表达式的值。 - 注意:表达式2的结果类型必须跟表达式3的结果类型一致,并且也要跟整个三元表达式的结果类型一致。
8.创建随机数
//1.创建一个能够产生随机数的对象
Random r = new random();
//2.让产生随机数的这个对象调用方法来产生随机数
int rNumber = r.Next(1,10) //取左不取右
8.复杂数据类型
1.常量
const int number = 10; 这就是定义了一个常量 常量是不可以改变的
e.g 超市哪一天打几折 这时候就可以用到常量了
2.枚举
- 起到了规范的作用 比如性别用男和女来命名 这时候就可以用枚举来规范
[public] enum 枚举名{ //public也可以省略 最好还是写出来
值1,
值2,
值3 //最后一个数据的后边逗号可以省略 表示是最后一个
} //定义枚举时可以在命名空间下类上声明或者类下函数前声明 绝对不能在函数里声明
将枚举声明到命名空间的下面,类的外面,表示这个命名空间下,所有的类都可以使用这个枚举。
//函数里
{
Discount d1 = Discount.nine;
Season s1 = Season.夏;
}
namespace _04枚举和int以及string类型之间的转换
{
public enum QQState
{
OnLine=1, //这也后边使用到枚举内容是第一个内容对应的数字是1 后边递增
OffLine,
Leave,
Busy,
QMe
}
public enum Gender
{
男,
女
}
class Program
{
static void Main(string[] args)
{
#region 将枚举类型强转成int类型
//QQState state = QQState.OnLine;
枚举类型默认可以跟int类型互相转换 枚举类型跟int类型是兼容的
//int n = (int)state;
//Console.WriteLine(n);
//Console.WriteLine((int)QQState.OffLine);
//Console.WriteLine((int)QQState.Leave);
//Console.ReadKey();
#endregion
#region 将int类型强转为枚举类型
//int n1 = 3; //如果n1为8(比枚举内容大) 则打印出来还是8
//QQState state = (QQState)n1;
//Console.WriteLine(state);
//Console.ReadKey();
#endregion
#region 将枚举类型转换成字符串类型
//所有的类型都能够转换成string类型
// int n1 = 10;
double n1 = 3.14;
// decimal n1 = 5000m;
// string s = n1.ToString();
// Console.WriteLine(s);
// Console.ReadKey();
//QQState state = QQState.OnLine;
//string s = state.ToString();
//Console.WriteLine(s);
//Console.ReadKey();
#endregion
#region 将字符串类型转换为枚举类型
//string s = "ABCDEFG";
将s转换成枚举类型
Convert.ToInt32() int.parse() int.TryParse() //转换的三种方法
调用Parse()方法的目的就是为了让它帮助我们将一个字符串转换成对应的枚举类型
//QQState state = (QQState)Enum.Parse(typeof(QQState), s); //如果输入的字符串枚举里边没有则会报错
//Console.WriteLine(state);
//Console.ReadKey();
#endregion
//枚举练习
//提示用户选择一个在线状态,我们接受,并将用户的输入转换成枚举类型。
//再次打印到控制台中
Console.WriteLine("请选择您的qq在线状态 1--OnLine 2--OffLine 3--Leave 4--Busy 5--QMe");
string input = Console.ReadLine();
switch (input)
{
case "1": QQState s1 = (QQState)Enum.Parse(typeof(QQState), input);
Console.WriteLine("您选择的在线状态是{0}",s1);
break;
case "2": QQState s2 = (QQState)Enum.Parse(typeof(QQState), input);
Console.WriteLine("您选择的在线状态是{0}",s2);
break;
case "3": QQState s3 = (QQState)Enum.Parse(typeof(QQState), input);
Console.WriteLine("您选择的在线状态是{0}",s3);
break;
case "4": QQState s4 = (QQState)Enum.Parse(typeof(QQState), input);
Console.WriteLine("您选择的在线状态是{0}", s4);
break;
case "5": QQState s5 = (QQState)Enum.Parse(typeof(QQState), input);
Console.WriteLine("您选择的在线状态是{0}", s5);
break;
}
Console.ReadKey();
}
}
}
3.结构
- 可以帮助我们一次性声明多个不同类型的变量。
- 语法:
[public] struct 结构名
{
public string _成员;//字段 加public这也下边也可以用
} - 变量在程序运行期间只能存储一个值,而字段可以存储多个值。
- 字段前边要加下划线
//结构和枚举的结合应用
namespace _02_结构练习
{
public enum Gender
{
男,
女
}
public struct Person
{
public string _name;
public int _age;
public Gender _gender; //应用了上边的枚举类型
}
class Program
{
static void Main(string[] args) {
Person zsPerson;
zsPerson._name = "张三";
zsPerson._gender = Gender.男;
zsPerson._age = 18;
Person xlPerson;
xlPerson._name = "小兰";
xlPerson._gender = Gender.女;
xlPerson._age = 16;
Console.WriteLine("我叫{0}是{1}的今年{2}岁了",zsPerson._name,zsPerson._gender,zsPerson._age);
Console.WriteLine("我叫{0}是{1}的今年{2}岁了",xlPerson._name,xlPerson._gender,xlPerson._age);
Console.ReadKey();
}
}
}
4.数组
- 一次性存储多个相同类型的变量。
- 语法 // 声明方式
数组类型[] 数组名=new 数组类型[数组长度];
int[] a = new int[10]; //定义了一个int类型长度为10的数组
int[] a = {0,1,2,3,4,5,6}; // 确定了数组初值
- 索引不能超过下界 数组的长度一旦固定了,就不能再被改变了
- int类型默认全为0 string默认全为null bool类型默认全为false
- null和“ ”空不一样 null没有开辟空间而空有
比较数组中的最大值最小值最好就是随便把数组内的一个值赋值给最大最小值 不要赋值为0
//将一个数组升序
int[] nums = {1,4,5,68,4,11,6};
Array.Sort(nums); //按升序顺序排序
Array.Reverse(nums); //将数组反转 顺序无变化
都是直接改变了数组
9.方法/函数
1.定义
函数的语法:
[public] static 返回值类型 方法名([参数列表])
{
方法体;
}
public:访问修饰符,公开的,公共的,哪都可以访问。
static:静态的
返回值类型:如果不需要写返回值,写void
// 平时写的Console.WriteLine(); 也是一种调用方法 调用的是Console这个类的WriteLine这个方法
-
在某些情况下,类名是可以省略的,如果你写的方法跟Main()函数同在一个类中,这个时候,类名可以省略。(不可以省略的例子看上方代码块注释部分)
-
方法写好后,如果想要被执行,必须要在Main()函数中调用。
方法的调用语法: 类名.方法名([参数]); -
写方法时既要写函数体和函数的作用 方便使用
2.调用
- 我们在Main()函数中,调用Test()函数,我们管Main()函数称之为调用者,
管Test()函数称之为被调用者。 - 如果被调用者想要得到调用者的值:
1)、传递参数。
2)、使用静态字段来模拟全局变量。 // public static int _number = 10;定义在类下和其他函数同级 - 如果调用者想要得到被调用者的值:通过返回值
- 不管是实参还是形参,都是在内存中开辟了空间的。
3.out、ref、params
1) out参数。
- 如果你在一个方法中,返回多个相同类型的值的时候,可以考虑返回一个数组。
- 但是,如果返回多个不同类型的值的时候,返回数组就不行了,那么这个时候,
我们可以考虑使用out参数。 - out参数就侧重于在一个方法中可以返回多个不同类型的值。
- 使用方法: 注意:方法内必须对out的参数进行赋值
static void Main(string[] args) {
int[] number = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
GetMaxMinSumAve(number, out int max, out int min, out int sum, out int ave);
Console.WriteLine("Max = {0},Min = {1},Sum = {2},Ave = {3}", max, min, sum, ave);
Console.ReadKey();
}
/// <summary>
/// 给定数组
/// 求最大最小值,总和,平均值
/// </summary>
/// <param name="nums">所求数组</param>
/// <param name="max">最大值</param>
/// <param name="min">最小值</param>
/// <param name="sum">总和</param>
/// <param name="ave">平均值</param>
public static void GetMaxMinSumAve(int[] nums, out int max, out int min, out int sum, out int ave) {
max = nums[0];
min = nums[1];
sum = nums[2];
ave = 0;
for (int i = 0; i < nums.Length; i++) {
if (nums[i] > max) {
max = nums[i];
}
if (nums[i] < min){
min = nums[i];
}
sum += nums[i];
}
ave = sum / nums.Length;
}
2) ref参数
- 能够将一个变量带入一个方法中进行改变,改变完成后,再讲改变后的值带出方法。
- ref参数要求在方法外必须为其赋值,而方法内可以不赋值。(因为要把值带到方法里边去 所以在方法外赋值)
- 使用方法
static void Main(string[] args) {
int n1 = 10;
int n2 = 20;
Swap(ref n1, ref n2);
Console.WriteLine("n1={0},n2={1}",n1,n2);
Console.ReadKey();
}
public static void Swap(ref int n1,ref int n2) {
int temp = n1;
n1 = n2;
n2 = temp;
}
3) params参数
- 将实参列表中跟可变参数数组类型一致的元素都当做数组的元素去处理。
- params可变参数必须是形参列表中的最后一个元素。
- 使用方法
static void Main(string[] args) {
int sum = GetSum(1,2,3,4,5,6,7,8,9);
Console.WriteLine(sum);
Console.ReadKey();
}
public static int GetSum(params int[] s) { //每个实参都变成了数组中的元素 最后结果为45
int sum = 0;
for (int i = 0; i < s.Length; i++) {
sum += s[i];
}
return sum;
}
4.方法重载 (同c++)
-
方法名字相同,参数不同
-
参数不同:
1.个数相同 则类型不能相同
2.类型相同 则个数不能相同
-
函数重载与返回值没关系
5.方法递归
- 使用方法
{
static void Main(string[] args) {
int i = 0;
All(i);
Console.ReadKey();
}
public static void All(int i) {
Console.WriteLine("从前有座山,山里有座庙,庙里有个小和尚和老和尚,老和尚对小和尚讲了个故事:");
i++;
if (i > 10) {
return;
}
All(i);
Console.WriteLine("我是第{0}次", i);
}
10.飞行棋项目
1.设置游戏界面
//设置前景色(文字的颜色)
Console.ForegroundColor = ConsoleColor.Red;//这是一个枚举 所以这样来调用
//设置背景色
Console.BackgroundColor = ConsoleColor.Red;
2.输入姓名
//输入后应该清屏
Console.Clear();
3.启动项目
//按下任意键投骰子
Console.ReadKey(true); //true 输入的任意键不会被显示 false为显示
- 对于一些变量可以设置为静态字段的数组 方便在不同方法中调用
- 方法要备注好
- 当用到大括号{}时 要在尾部注释这是哪个语句的 //while //else