C#学习笔记 从入门到进阶

一,入门知识

1. 输入输出

//输出空行
Console.WriteLine("hello world!");

//输出不空行
Console.Write("hello world!");

//读入一行
Console.ReadLine();

//一键输入
Console.ReadKey();

2.变量

  • 有符号变量:

           sbyte:-128~127,int:-21亿~21亿多,short:-32768~32767 ,long:-9百万兆~9百万兆

  • 无符号整形变量:

         byte: 0~255, uint:0~24亿多, ushort:0~65535,ulong: 0~18百万兆

  • 浮点数

        float:7~8位有效数字(0之后的有效数字),会四舍五入

        在最后加上f(在C#中小数默认为double类型,只有加了f才能算为float类型)        

float f = 0.01234567890f;

        double :储存15~17位有效数字

        decimal : 存储27~28位有效数字,后面要加m,会四舍五入

  • 特殊类型

        bool true false表示真假,char 单个字符(加上‘ ’),string 字符串(加上“ ”)

 3.常量(必须有初始值)(不可被改变)

        const  类型  名字  = 初始值;

4.折叠代码

        #region 名字

                代码内容

        #endregion

5.转义字符 \+符号,取消转义字符:在前面+@

6.类型转换

  • 隐式转换:大范围 转 小范围

        相同大类型之间的转换  : long->int->short->sbyte;ulong->uint->ushort->byte;double -> float(decimal不可以用隐式转换变成double,但是可以隐式转换整型);特殊类型(bool,char,string之间不存在隐式转换)

        不相同大类型之间的转换  : 无符号的数 不能隐式转换装 有符号的数 ; 有符号的数 装 范围比它小的无符号数;浮点数 装 任何类型的整数;整数 不能隐式转换装 浮点数;char类型 隐式转换成整型和浮点型(ASCII码)

        总结:隐式转换规则

高精度-> 低精度

double->float->整型(有符号,无符号)->char

decimal->整型(有符号,无符号)->char

string和bool不参与隐式转换规则

  •    显示转换

括号转换,但是要注意范围问题和精度问题。

parse转换:变量类型.parse(字符串); 要注意只有字符串可以转换为该类型的才可以用parse。

convert法:   convert.To目标类型(变量或常量),会四舍五入,

其他类型转string: 变量.toString();

7.异常捕获

作用:避免当代码报错时,出现程序卡死的情况

写法:

//必备部分
try
{
    //可能出现异常的代码块放入其中
}
catch
{
    //出现问题后执行catch中的代码
    //catch(Exception e)可以带着try中的错误原因进入catch,可以打印
}
//可选部分
finally
{
    //无论出现异常与否,都会执行
}

8.算数运算符(太简单了不写)

9.字符串拼接

用+拼接: str1+str2;

用固定语法拼接:

string str = string.Format("我是{0},我今年{1}岁,我想要{2}",mood,18,"天天学习,好好向上");
Console.Writeline(str);

在写待拼接内容里占位符{数字},数字由0·9

控制台打印:

Console.WriteLine("A{0}B{1}c{2}",1,true,false);
Console.Write("A{0}B{1}c{2}",1,true,false);

注意:后面不能比占位符少,否则会报错

二,基本知识

1.复杂数据类型

A.枚举

1.枚举是一个被命名的整型常量的集合,一般被用来表示状态,类型等

2.申明枚举:创建一个自定义的枚举类型

   申明枚举变量:使用申明的自定义枚举类型,创建一个枚举变量

3.申明枚举语法:

enum E_自定义名称
{
    自定义枚举项名字0,
    自定义枚举项名字1,
    自定义枚举项名字2,
    自定义枚举项名字3,
    //第一个默认值为0,其他依次累加
    //如果给其中某一个赋值,剩下的也还是会依次累加
}

4.枚举申明地方:namespace语句块中,struct中,不能在函数语句块中申明

5.枚举的使用:(配合条件语句,if else,和switch)

自定义枚举类型  自定义名称 = 默认值(自定义枚举类型.枚举项);

E_monsterType monster1 = E_monsterType.Boss;
if(monster1 == E_monsterType.Boss)
{
    Console.WriteLine("Boss");
}
else
{
    Console.WriteLine("normal");
}

E_palerType player1 = E_palerType.Main;
switch (palyer1)
{
    case:E_plaerType.Main;
        break;
    case:E_plaerType.Other;
        break;
    default:
        break;
}

6.枚举的类型转换

枚举和int转换: int i = (int)playerType;

枚举和string转换:string str = playerType.ToString

(就是转换为枚举项的名字,比如main或者other)

string和枚举的转换:

playerType = (E_playerType)Enum.Parse(typeof(E_playerType),“other”);

(playerType = other)

枚举例题

namespace Study
{
    enum E_qqType
    {
        Online,
        Busy,
        Leave,
        Individual,
    }

    enum E_coofeType
    {
        M,
        B,
        S,
    }

    enum E_gamePerson
    {
        man,
        woman,
        zhanshi,
        lieren,
        fashi,

    }
    internal class Program
    {
        static void Main(string[] args)
        {
            #region    QQ状态
            try
            {
                 Console.WriteLine("请输入QQ状态:(0在线,1忙碌,2离开,3隐身)");
                int type = int.Parse(Console.ReadLine());
                E_qqType qqType = (E_qqType)type;
                Console.WriteLine(qqType);
                Console.WriteLine();

            }
            catch
            {
                Console.WriteLine("请输入数字");
            }
            #endregion

            #region  星巴克咖啡
            try
            {
                Console.WriteLine("请输入你想要的size(0中杯,1大杯,2超大杯)");
                int type = int.Parse(Console.ReadLine());
                E_coofeType cafe = (E_coofeType)type;
                switch (cafe)
                {
                    case E_coofeType.M:
                        Console.WriteLine("你购买了中杯咖啡,消费35元");
                        Console.WriteLine();
                        break;
                    case E_coofeType.B:
                        Console.WriteLine("你购买了大杯咖啡,消费40元");
                        Console.WriteLine();
                        break;
                    case E_coofeType.S:
                        Console.WriteLine("你购买了超大杯咖啡,消费43元");
                        Console.WriteLine();
                        break;
                }
            }
            catch
            {
                Console.WriteLine("请输入数字:");
            }

            #endregion

            #region  游戏人物
            try
            {
                string sexString = " ";
                string jueseString = " ";
                string zhiyeString = "";
                int gongji = 0;
                int fangyu = 0;
                Console.WriteLine("请输入你想选择的性别(0男,1女)");
                int sexy = int.Parse(Console.ReadLine());
                Console.WriteLine("请输入你想选择的角色(2战士,3猎人,4法师)");
                int juese = int.Parse(Console.ReadLine());

                E_gamePerson p = (E_gamePerson)sexy;
                switch(p){
                    case E_gamePerson.man:
                        sexString = "男性";
                        gongji += 50;
                        fangyu += 100;
                        break;
                    case E_gamePerson.woman:
                        sexString = "女性";
                        gongji += 150;
                        fangyu += 20;
                        break;
                }

                E_gamePerson q = (E_gamePerson)juese;
                switch (q)
                {
                    case E_gamePerson.zhanshi:
                        gongji += 20;
                        fangyu += 100;
                        jueseString = "战士";
                        zhiyeString = "冲锋";
                        break;
                    case E_gamePerson.lieren:
                        gongji += 120;
                        fangyu += 30;
                        jueseString = "猎人";
                        zhiyeString = "假死";
                        break;
                    case E_gamePerson.fashi:
                        gongji += 200;
                        fangyu += 10;
                        jueseString = "法师";
                        zhiyeString = "奥术冲击";
                        break;
                }

                Console.WriteLine("你选择的角色是\"" + sexString +jueseString+"\","+"攻击力:"+gongji+",防御力:"+fangyu+",职业技能"+zhiyeString);
                Console.WriteLine();
            }
            catch
            {
                Console.WriteLine("请输入正确的选择内容");
            }

            #endregion
        }
    }
}

B.数组

1、一维数组

数据类型 [ ] 数组名称 = new 数据类型 [ 数组长度 ] {内容1,内容2.....};

数据类型 [ ] 数组名称 = {内容1,内容2......};

2.多维数组

数据类型 [ ,]  数组名称 = new 数据类型[行,列];

3.交错数组(了解)

定义:数组的数组,每行的列可以不同

数据类型 [ ] [ ]  数组名称 = new 数据类型 [行 ] [ ] ;

数据类型 [ ] [ ]  数组名称 = {{一维数组1},{一维数组2},.......};

int [ ][ ] arr1 = new int [3][ ] {new int [ ] {1,2,3} , new int [ ] {1,2} , new int [ ] {1}};

2.值类型和引用类型 

1.string,数组,类时,为引用类型。其他为值类型

2.值类型在相互赋值时,将内容拷贝给对方,你变我不变

   引用类型是相互赋值,你变我也变

3.两者不同的原因:

        值类型存储在栈里 —— 系统分配,自动回收,小而快; 

        引用类型存储在堆里 —— 手动申请,大而慢;

4.string很特殊,有值类型的特征,他变我不变 

 

3.函数

  A.ref和out的使用

        当传入的值类型参数在内部被修改  或  引用类型参数在内部重新申明的时候,外部也会发生改变。

a.ref的使用

//函数的设置
static void changeValue(ref int a) {
    a = 3;
}

static void changeArray(ref int[] arr){
    arr = new int[] {100,200,300};
}

//参数的传入
int a = 1;
changeValue(ref a);
Console.Writeline(a);//3

int[] arr1 = {1,2,3};
changeArray(ref arr1);
Console.WriteLine(arr[0]);//100

b.out的使用:将ref改为out

  B.ref和out的区别

  • ref传入的变量必须初始化,在内部可改可不改
  • out传入的变量不必初始化,在内部必须赋值

4.变长参数和参数默认值

A.变长参数

关键字:params

static int add(params int[] arr){
    int sum = 0;
    for(int i = 0;i < arr.length;i++){
        sum += arr[i];
    }
    return sum;
}

....

add(1,2,3,66,880,325,678);
  • 可以传入n个对应类型的数值,n>=0
  • parmas 后面跟的一定是数组,传入的数值会存入数组中
  • 类型可以是任何类型
  • 函数参数可以有别的参数 和 params修饰的参数 ,但是params修饰的参数必须是最后一个,且只能出现一次

B.参数默认值

  • 有参数默认值的参数称为可选参数,可赋可不赋值
  • 可以有多个参数默认值,但是必须放在普通参数后面 
//函数设置
static void Eat(String food = "黄焖鸡米饭"){
    Console.Write(food);
}

//函数的调用
Eat();  //黄焖鸡米饭
Eat("火锅");  //火锅

//当函数传入参数时,在函数的内部使用传入的参数,当函数没有传入参数时,就使用可选参数

 5.重载函数

定义:在同一领域如struct或者class下,同一个函数名,传入的参数数量,类型,顺序不同的函数

注意:与返回值无关

适用范围:当不同类型有同一函数逻辑时就用重载函数

6.结构体

  • 结构体内变量不能赋值
  • 可以包含别的结构体,但是不能包含自己
  • 结构体函数中可以直接使用结构体内部已申明的变量
  • 结构体的构造函数:与结构体名字相同,无返回值,有参数,this.name = name,在外界传参时用  结构体名 名字 = new 构造函数名字(参数); 

三,核心知识 

1.类和对象

  • 类是引用类型
  • 类对象的基本语法
class Person{

}


Person p ;//只分配栈空间
Person p1 = NULL;//只分配栈空间
Person p2 = new Person();//开辟一个堆空间

2.成员变量 和 访问修饰符

成员变量:

  • 成员变量可以是多个,可以赋初值,但大部分时间是不赋的,因为每个个体都不一样
  • 如果要在类中申明一个和自己类型相同的成员变量,是不可以对它进行实例化的,会造成死循环

访问修饰符:

  • public,公共的,内部和外部都可以访问
  • private,私有的,只有内部可以使用(不写默认为private)        
  • protect,保护的,只有内部和子类可以使用

成员变量的使用和初始值:

  • 值类型:数字类型都是0,bool类型是false
  • 引用类型:null

3.成员方法

namespace ChengYuanBianLiang
{
    internal class Program
    {
        class Person()
        {
            public String name;
            public int age;
            
            /// <summary>
            /// 吃饭
            /// </summary>
            /// <param name="food"></param>
            public void Eat(String food)
            {
                Console.WriteLine("{0}吃了{1}",name,food);
            }

            /// <summary>
            /// 说话
            /// </summary>
            /// <param name="str"></param>
            public void Spea(String str)
            {
                Console.WriteLine("{0}说{1}",name,str);
            }

            /// <summary>
            /// 走路
            /// </summary>
            /// <param name="walk"></param>
            public void Walk(bool walk)
            {
                if (walk)
                    Console.WriteLine("{0}正在走路",name);
                else 
                    Console.WriteLine("{0}正在休息",name);
            }
        }

        class Student()
        {
            public String name;
            public String ClassName;
            public int number;

            public void study(bool x)
            {
                if (x)
                {
                    Console.WriteLine("{0}正在学习", name);
                }
                else
                {
                    Console.WriteLine("{0}没有学习", name);
                }
            }

            public void Eat(String food)
            {
                
                Console.WriteLine("{0}今天吃了{1}", name, food);

            }
        }

        class Food()
        {
            public String name;
            public int hotNums;
        }

        static void Main(string[] args)
        {
            Console.WriteLine("person类");
            Person p = new Person();
            p.name = "蔡徐坤";
            p.age = 18;
            p.Eat("黄焖鸡");
            p.Spea("黄焖鸡真好吃");
            p.Walk(false);

            Console.WriteLine();
            Console.WriteLine("Student类");
            Student s = new Student();
            s.name = "Jam";
            s.ClassName = "计算机科学与技术一班";
            s.number = 1;
            s.study(true);
            s.Eat("水饺");

            Console.WriteLine();
            Console.WriteLine("Food类");
            Food f1 = new Food();
            f1.name = "水饺";
            f1.hotNums = 100;
            Food f2 = new Food();
            f2.name = "黄焖鸡";
            f2.hotNums = 140;
        }
    }
}

4.构造函数,析构函数

A.构造函数

  • 在实例化对象时,会用于初始化函数,如果不写则默认存在一个无参构造函数
  • 如果只写了有参构造函数,那么无参构造函数会默认不存在
  • 构造函数没有返回值  函数名必须和类名相同  没有特殊要求一般是public
  • this用于表示当前被调用的自己
class People
{
    public String name;
    public int age;

    //无参构造函数
    public People()
    {
        name = "Jame";
        age = 18;
    }

    //有参构造函数
    public People(String name,int age)
    {
        this.name = name;
        this.age = age;
    }
}

B.析构函数

当引用内存的堆内存被回收时,就会调用析构函数(在Unity中几乎不会使用析构函数)

析构函数是当垃圾被回收时才会被调用

~类名
{

}

C.垃圾回收(GC)

  • 垃圾回收过程是遍历堆上动态分配的所有对象
  • 垃圾就是没有被任何变量,对象引用的内容
  • GC只管堆(heap)内存的释放和回收,栈(stack)归系统管理,有它自己的生命周期

手动调用GC,当lading条过场景的时候就会调用GC

GC.Collect();

5.成员属性

A.成员属性的写法

在get中需要return内容,在set中需要value来传入内容

 class Person
 {
     private string name;
     private int age;
     public string Name
     {
         get
         {
             return name;
         }
         set
         {
             //赋值
             name = value;
         }
     }

static void Main(string[] args)
{
    Person p = new Person();
    p.Name = "mood";  //调用get()
    Console.WriteLine(p.Name);  //调用set()
}

B.加密与解密:存进去的东西和输入的东西不一样,起到了加密的作用

public string Name
{
    get
    {
        return name - 5;
    }
    set
    {
        //赋值
        name = value + 5;
    }
}

C.成员属性在get和set前面加修饰符,解决3p的局限性

  • 默认不加会使用属性申明时的访问权限
  • 加的访问修饰符不能低于属性申明时的访问权限
  • 不能都低于属性申明时的访问权限

D.get和set可以只有一个

当只给不得时,只有get;只改不得,只有set 

E.自动属性

当一个属性只希望被外界只得不改,而且没有什么特殊要求的时候(比如解密加密,判断大小等等),就用自动属性,可以简约代码

//只得不改
public float Height
{
    get;
    private set;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值