C#基础4笔记

1.访问修饰符

作用

所有类型和类型成员都具有可访问性级别(权限)

分类

public:同一程序集的其他任何代码或引用该程序集的其他程序集都可以访问该类型成员。(公有)

internal:同一程序集中的任何代码都可以访问该类型或成员,但其他程序集不可以访问。(私有)

private:同一类和结构的代码可以访问该类型和成员。(本地)

protected:同一类和继承特性类中的代码可以访问该类型和成员。

protected internal:同一程序集中的任何代码或其他程序集中的任何继承特性的类都可以访问该类成员。

private protected:该类型或成员可以通过从class继承特性类的类型访问。

C#的默认修饰符

类、结构体的默认修饰符是internal。

类中所有的成员默认修饰符是private。

接口默认修饰符是internal。

接口的成员默认修饰符是public。

枚举类型成员默认修饰符是public。

委托的默认修饰符是internal。

2.C#方法(函数)

作用:

方法是包含一系列语句的代码块。方法必须在类或结构中声明

优点:

减少代码重复率

方法体现了C#语言的封装性

方法分为 声明方法(定义方法) 和 调用方法(使用方法)

声明方法基本结构

访问权限        静态或非静态        返回值类型        方法名称    ( 方法参数){         语句块       }

访问权限:访问修饰符

静态或非静态:static(静态)        非静态(不写)

返回值类型:代表方法是否具有  return  数据的类      void(空)  和  其他明确的数据类型(int  float string。。。)

方法名称:大驼峰命名        见名知意

方法参数:实参(调用方法) 和        形参(声明方法)

调用方法:

在哪调用?(在方法内部调用        Main 入口方法  程序运行时  自动执行  Main方法是静态方法  自定义静态方法直接使用,自定义非静态方法  需要对象打点调用)

方法的分类:

从访问权限分类

从静态和非静态分类

从有无参数分类

从有无返回值分类

参数传递 形式:

值参数:

特点:

1.参数传递的默认方式

2.当调用一个方法时,会为每个值参数创建一个新的存储位置。

3.当形参的值发生改变,不会影响实参的值,从而保证了实参数据的安全

总结:无论参数的类型是值类型还是引用类型  都遵循值传递的特性

public void swap (int x,int y)
{
    int temp;
    temp = x;        //保存x的值
    x = y;              //把y赋值给x
    y = temp;        //把temp赋值给y
}
 引用参数

特点:

1.引用参数是一个对变量的内存位置的引用  不会创建一个新的存储位置

2.参数关键字 ref

    //值参数传递
    int d = 1;
    int c = 2;
    TestMothod(d, c);
    Console.WriteLine("d的值为:" + d);
    Console.WriteLine("c的值为:" + c);

    //引用参数传递
    int w = 3;
    int x = 4;
    TestMothod1(ref w, ref x);
    Console.WriteLine("w的值为:" + w);
    Console.WriteLine("x的值为:" + x);

    int tempA = TestMothod2();
    Console.WriteLine(tempA);


    //int tempB;
    //int.TryParse(Console.ReadLine(), out tempB);


    string stringB;
    int tempNum = TestMothod4(out stringB);
    Console.WriteLine("temoNum结果为:"+tempNum);
    Console.WriteLine("stringB结果为:"+stringB);


    string tempResult;

    int sumNum = Sum(1, 2, out tempResult);
    Console.WriteLine(sumNum);
    Console.WriteLine(tempResult);




    Console.ReadKey();
}

public static void TestMothod(int a,int b)
{

    int temp = 0;
    temp = a;
    a = b;
    b = temp;
    Console.WriteLine("a的值为:" + a);
    Console.WriteLine("b的值为:" + b);
}

public static void TestMothod1(ref int a,ref int b)
{

    int temp = 0;
    temp = a;
    a = b;
    b = temp;
    Console.WriteLine("a的值为:" + a);
    Console.WriteLine("b的值为:" + b);
}

public static int TestMothod2()
{

    //跳出方法(结束方法)
    //把1返回到方法的外部
    return 1;
}

public static void TestMothod3()
{

    //跳出方法(结束方法)
    return;
}

public static int TestMothod4(out string b)
{

    //跳出方法(结束方法)
    //把1返回到方法的外部

    b = "abc";
    return 1;
}
输出参数

特点 :

1.是对于方法返回值类型的补充。return语句可用于函数中返回一个值  输出参数可以返回多个值

2.关键字out  out输出参数在方法中 必须被使用,且和return保持一致

3.其他方面与引用参数相似
 

 public static int Sum(int a,int b,out string resultStr)

 {

     if (a + b > 10)

     {

         resultStr = "结果大于10";

     }

     else

     {

         resultStr = "结果小于10";

     }

     return a + b;

 }

 public static void Sum1(int a, int b, out string resultStr, out int c)

 {

     if (a + b > 10)

     {

         resultStr = "结果大于10";

     }

     else

     {

         resultStr = "结果小于10";

     }

     c = a + b;

 }
可变参数params(讲完数组再说)

1.params是ParamArrayAttribute(参数数组属性)的缩写

2.param解决了C#中不定参数的传递的问题

3.params参数必须定义在参数列表最后面。

4.params必须是一维数组

5.params只能在一个方法中 定义一个一维数组

static void ParamtesDemo(string className, params string[] names)
        {
               string tempStr = "";
              foreach (string name in names)
               {
                    tempStr += name;  
               }
                Console.WriteLine($"{className}的学生有:{tempStr}");
         }
ParamtesDemo("223班级", "张三", "李四", "王五", "赵六");
递归方法调用

一个方法可以自我调用。这就是所谓的  递归

C#空类型(Null)

1.Null

特点:

1.表示不引用任何对象的空引用,没有创建内存空间,存放的是空引用指针;

2.Null类型是System.Nullable<T>这个struct的类型

3.对于值类型 赋值不能直接为Null 引用类型可以

4.null引用类型变量的默认值

值类型如何赋值为null?

1.Nullable<T>结构体

Nullable<int> intNumber = null;

2.类型之后添加 单?

int? intNumber = null;
 使用场景:

当我们想要对于一个值类型变量进行 判断 是否 存在时,为了节约内存 可以赋值为nill

null和字符串空值和字符串空格的区别

1.null是没有创建内存空间的。

2.字符串空值 为"" 或者string.Empty 实际上都会分配空间;

3.字符串空格"  " 会分配空间 空格也是ACSll 对应的符号

            string str = "123"; //正常字符串,有值非空
            string str1 = null;  //值为null
            string str2 = "";    //是个空字符串
            string str3 = "    ";//空白字符串,双引号之间是空格或者Tab键
            Console.WriteLine(string.IsInterned(str));
            Console.WriteLine(string.IsInterned(str1));
            Console.WriteLine(string.IsInterned(str2));
            Console.WriteLine(string.IsInterned(str3));
 
 
             IsInterned方法 判断数据是否已经存在于内存中

不可变数组

含义:

不可变数组是一个存储相同类型元素的固定大小的顺序集合

特点:

数组属于引用类型

数组只能包含类型相同的元素

数组通过下标(索引值)标记元素  下标从0开始  一次加1

格式:
声明数组:

datatype[] arrayName

  • datatype 用于指定被存储在数组中的元素的类型
  • 指定数组的秩(维度)。秩指定数组的大小
  • arrayName  指定数组的名称。
初始化数组中的元素的方式(使用数组)

数据类型 [ ]  数组名={值1,值2,。。。}

数据类型 [ ]  数组名=new 数据类型  [ 长度 ] {值1,值2,。。。}

数据类型 [ ]  数组名=new  数据类型 [长度可忽略] {值1,值2,。。。}

数据类型 [ ]  数组名=new  数据类型[长度]

数组访问元素:

intArray[0] 

修改数组元素:

intArray[0]=1

遍历数组方式:

for

foreach

int[] intArray2 = {1,2,3,4,5,6 };

            for (int i = 0; i < intArray2.Length; i++)
            {
                Console.WriteLine(intArray2[i]);
            }
            foreach (var item in intArray2)
            {
                Console.WriteLine(item);
            }


 

数组越界  超出数组范围  系统抛出异常 
System.IndexOutOfRangeException:“索引超出了数组界限

多维数组 

含义:数组嵌套数组形式  一般常用二位数组

二维数组格式:string[,]  strArray=new string[数组个数,数组元素个数]

初始化二维数组
 /* 一个带有 5 行 2 列的数组 */
            int[,] a = new int[5, 2] {{0,0}, {1,2}, {2,4}, {3,6}, {4,8} };
 二维数组访问元素:

int val = a[2,3];

二维数组修改元素:

a[2,3]=10;

遍历二维数组元素
     for (int i = 0; i < studentArray.GetLength(0); i++) {

                for (int j = 0; j < studentArray.GetLength(1);j++) {

                    Console.WriteLine(studentArray[i, j]);
                }
                
            }
 其他多为数组格式:例如三维数组  string [,,]  strArray=new  string [ 数组个数 ,  数组元素个数 ]

int[,,] val = new int[3, 3, 3]    { { { 10, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } },

                          { { 10, 11, 12 }, { 13, 14, 15 }, { 16, 17, 18 } },

{ { 19, 20, 21 }, {22, 23, 24 }, { 25, 26, 27 } } };

三维数组访问元素:

int val = a[2,2,2];

三维数组修改元素:

a[2,2,2]=10;

遍历三维数组元素
  int[,,] tempArray = new int[2, 2, 2] { { {1,2 },{3,4 } },{ {5,6 },{7,8 } } };

            for (int i = 0; i < tempArray.GetLength(0); i++)
            {

                for (int j = 0; j < tempArray.GetLength(1); j++)
                {

                    for (int k = 0; k < tempArray.GetLength(2); k++) {
                        Console.WriteLine(tempArray[i,j,k]);

                    }
                 
                }

            }

交错数组  了解 

含义

交错数组是数组的数组,交错数组是一维数组。

交错数组格式:

int [ ] [ ] scores;

初始化交错数组中的元素的方式

int [ ] [ ] score = new int [2][ ] {new int [ ] {92,93,94},new int[ ]{85,86,87}};

交错数组访问元素:

scores[0][1]

交错数组修改元素:

scores[0][1]=10;

Array 类

含义:

是C#中所有数组的基类,它是在 System 命名空间中定义  提供了各种用于数组的属性和方法

常用属性 和方法

CreateInstance(typeof(int), 5);  //创建一维数组

Array aa=     Array.CreateInstance(typeof(int), 5);
  aa.SetValue(0, 1);
  aa.GetValue(0);

  Array asa  =Array.CreateInstance(typeof(int), 2,2);//创建二维数组
    asa.SetValue(0, 1);

    asa.SetValue(0, 2)

     asa.SetValue(1, 2);

     asa.GetValue(1, 1);

Indexof(Array array, Obejct)    返回第一次出现的下标(数组元素索引值)
Sort(Array array)    从小到大排序 (仅支持一维数组)
Reverse(Array array)    数组逆置(数组顺序倒过来)
Clear(Array array, int index, int length)    将某个范围内的所有元素设为初始值
Copy      深复制   数组内容到另一个数组

    //创建一维数组
            int[] intArray = new int[5];
            intArray[0] = 1;
            intArray[1] = 20;

            Console.WriteLine(intArray[0]);
            //参数1 数组的数据类型
            //参数2 数组的长度
             Array  intArray1 =    Array.CreateInstance(typeof(int),5);
             //赋值
             intArray1.SetValue(10,0);
             intArray1.SetValue(20,1);

             Console.WriteLine(intArray1.GetValue(0));
             //修改
             intArray1.SetValue(30, 0);
             Console.WriteLine(intArray1.GetValue(0));

            创建二维数组
            int[,] intArray3 = new int[2,2];
            intArray3[0, 0] = 100;
            intArray3[0, 1] = 200;
            Console.WriteLine(intArray3[0,0]);


            Array intArray2= Array.CreateInstance(typeof(int), 2,2);
            intArray2.SetValue(100,0,0);
            intArray2.SetValue(200,0,1);

            Console.WriteLine(intArray2.GetValue(0,0));




            //案例:查找当前数组中是否存在 整数1
            //参数1:要查询的数组对象
            //参数2:查询的数组元素
            int indexNum =  Array.IndexOf(intArray, 1);

            string str =   indexNum == -1 ? "元素不存在" : "元素存在";
            Console.WriteLine(str);

            int[] intArray4 = new int[5] { 100, 30, 20, 200, 1 };
             //从小到大  升序
            Array.Sort(intArray4);

            foreach (var item in intArray4)
            {
                Console.WriteLine(item);
            }
            
             //倒序排列
            Array.Reverse(intArray4);
            foreach (var item in intArray4)
            {
                Console.WriteLine(item);
            }
            //将某个范围内的所有元素设为初始值
            Array.Clear(intArray4, 1, 2);
            foreach (var item in intArray4)
            {
                Console.WriteLine(item);
            }

            int[] intArray5 = new int[6];

            //复制数组  深复制
            Array.Copy(intArray4,intArray5,intArray4.Length);

            foreach (var item in intArray5)
            {
                Console.WriteLine(item);
            } 

 不可变字符串

含义:

string,引用类型,string类型表示零或更多Unicode字符组成的序列,

string 是 . NET Framework 中 String 的别名。

初始化字符串方式

   //字面量初始化字符串
     string str = "abc";

     //方式1   字面量创建字符串
     string str1 = "abc";
     string str2 = @"abc";

     //方式2
     char[] charArray = new char[5] { 'a', 'b', 'c', 'd', 'f' };
     string str3 = new string(charArray);
     Console.WriteLine(str3);

     //方式3
     string str4 = string.Format("123");

     //字符串本质也是单字符的集合
     string str5 = "abcdeadeGHFGE";
     Console.WriteLine(str5.Length);

     //获取某一个单字符
     char tempChar = str5[1];
     Console.WriteLine(tempChar);
     //遍历字符串
     for(int i=0;i<str5.Length;i++)
     {
         Console.WriteLine(str5[i]);
     }

     foreach(char item in str5)
     {
         Console.WriteLine(item);
     }

     //修改字符串中的某个元素
     //不可直接修改
     //str5[2] = '2';

字符串常用API

    1.Length 获取字符串的长度,即字符串中字符的个数.

    2.IndexOf 返回整数,得到指定的字符串在原字符串中第一次出现的位置.

    3.LastlndexOf 返回整数,得到指定的字符串在原字符串中最后一次出现的位置.

    4. StartsWith 返回布尔型的值,判断某个字符串是否以指定的字符串开头.

       

    5. EndsWith 返回布尔型的值,判断某个字符串是否以指定的字符串结尾.

       

    6. ToLower 返回一个新的字符串,将字符串中的大写字母转换成小写字母.

       

    7. ToUpper 返回一个新的字符串,将字符串中的小写字母转换成大写字母.

       

    8. Trim返回一个新的字符串,不带任何参数时表示将原字符串中前后的空格删除.

       

    9. Remove 返回一个新的字符串,将字符串中指定位置的字符串移除.

    10. TrimStart 返回一个新的字符串,将字符串中左侧的空格删除.

       

    11. TrimEnd 返回一个新的字符串,将字符串中右侧的空格删除。

       

    12. PadLeft 返回一个新的字符串,从字符串的左侧填充空格达到指定的字符串长度.

       

    13. PadRight 返回一个新的字符串,从字符串的右侧填充空格达到指定的字符串长度.

       

    14. Substring 返回一个新的字符串,用于截取指定的字符串.

       

    15. Insert 返回一个新的字符串,将一个字符串插入到另一个字符串中指定索引的位置.

        

    16.concat 

    17.contain  字符串是否包含某个字符串  (区分大小写)

    18.IsNullOrEmpty  判断字符串对象是否为空类型或者是空字符串

    19. char[] charArray = str.ToCharArray();    //ToCharArray  把字符串分割成字符数组

    20.str1.Split(',') 以特殊符号为参考分割字符串为字符串数组

    21 Join  //把数组组合成字符串  以某个字符作为组合符号


            //字符串api
            //1.Length  获取字符串的长度,即字符串中字符的个数
            Console.WriteLine(str5.Length);

            //2.IndexOf 返回整数,得到指定的字符串在原字符串种第一次出现的位置.
            int indexNum = str5.IndexOf('a');

            if(indexNum != -1)
            {
                Console.WriteLine("1结果等于"+indexNum);
            }
            else
            {
                Console.WriteLine("2结果等于" + indexNum);
            }

            //3.LastIndexOf 返回整数,得到指定的字符串在原字符串中最后一次出现的位置

            int indexNum1=str5.LastIndexOf("a");

            if(indexNum1 != -1)
            {
                Console.WriteLine("3结果等于"+indexNum1);
            }
            else
            {
                Console.WriteLine("4结果等于" + indexNum1);
            }

            //4.StartsWith 返回布尔型的值,判断某个字符是否以指定的字符串开头
            bool isTrue = str5.StartsWith("abcd");
            if (isTrue)
            {
                Console.WriteLine("是开头");
            }
            else
            {
                Console.WriteLine("不是开头");
            }

            //5.EndWith 返回布尔型的值,判断某个字符串是否以指定的字符串结尾。
            //string str5 = "abcdefg";

            //6.ToLower 返回一个新的字符串,将字符串中的大写字母转换成小写字母。

            string LowerStr5 = str5.ToLower();
            Console.WriteLine(str5);
            Console.WriteLine(LowerStr5);

            //7.ToUpper 返回一个新的字符串,将字符串中的小写字母转换成大写字母

            //8. Trim 返回一个新的字符串,不带任何参数时表示将原字符串中前后的空格删除

            string str6 = "abc";
            string trimStr6 = str6.Trim();
            Console.WriteLine(str6);
            Console.WriteLine(trimStr6);
            Console.WriteLine(str6.Length);
            Console.WriteLine(trimStr6.Length);

            //9.TrimEnd 返回一个新的字符串,将字符串中右侧的空格删除。           

            //10.TrimStart 返回一个新的字符串,将字符串中左侧的空格删除。

            //11.Remove 返回一个新的字符串,将字符串中指定位置的空格删除
            //string str5 = "abcdeGhfg";
            string removeStr5 = str5.Remove(6, 2);
            Console.WriteLine(str5);
            Console.WriteLine(removeStr5);

            //12.PadLeft 返回一个新的字符串,从字符串的左侧填充空格达到指定的字符串长度

            //13.PadRight 返回一个新的字符串,从字符串的右侧填充空格达到指定的字符串长度

            //14.Substring 返回一个新的字符串,用于截取指定的字符串

            string subStr5 = str5.Substring(2);
            Console.WriteLine(subStr5);
            string subStr51 = str5.Substring(2, 3);
            Console.WriteLine(subStr51);

            //15.Insert 返回一个新的字符串,将一个字符串插入到另一个字符串中指定索引的位置

            string insertStr5 = str5.Insert(7, "WD");
            Console.WriteLine(str5);
            Console.WriteLine(insertStr5);

            //16.concat 后续讲
            //str5.Concat<>;

            //17.Contains 字符串是否包含某个字符串   (区分大小写)
            bool isTrue1 = str5.Contains("gh");
            Console.WriteLine(isTrue1);

            //18.IsNullOrEmpty  判断字符串对象是否为空类型或者是空字符串
            Console.WriteLine("请输入字符串:");

            string tempStr = Console.ReadLine();

            string tempStr1 = "abc";

            if (string.IsNullOrEmpty(tempStr))
            {
                Console.WriteLine("输入字符串异常");
            }
            if (tempStr == null || tempStr == "")
            {
                Console.WriteLine("输入字符串异常");
            }
            else
            {
                Console.WriteLine(tempStr + tempStr1);
            }

            //19.ToCharArray    把字符串分割成字符数组
            string str7 = "abcdef";
            char[] charArray1 = str7.ToCharArray();

            foreach(var item in charArray1)
            {
                Console.WriteLine(item);
            }
            //str7[0] = 'w';
            charArray1[0] = 'w';

            //20.Split(',') 把字符串转换成数组
            string str8 = "a,b,c,d,e,f,w";
            string[] testArray = str8.Split(',');//a b c d e f w    string[] test={a,b,c,d,e,f,w};

            foreach(var item in testArray)
            {
                Console.WriteLine(item);
            }

            string str9 = "axbxcxwxf";
            string[] testArray1 = str9.Split('x');
            foreach(var item in testArray1)
            {
                Console.WriteLine(item);
            }

            string str10 = "abx,cwf";
            string[] testArray2 = str10.Split();
            foreach(var item in testArray2)
            {
                Console.WriteLine(item);
            }

            //21.Join 把数组组合成字符串 以某个字符作为组合符号

StringBuilder类的使用

特点:

1.可以定义可变字符串,实现字符串的添加

2.对于高频率字符串拼接可以使用

3.如果普通拼接 可以使用上节课所讲的字符串格式化方式

常用方法如下:

Append 末尾追加

Insert 在指定位置插入指定字符串

Remove 移除指定字符串

//普通拼接方法  (低效率 会频繁开辟不连续的内存空间 )
            string str = string.Empty;
            str += "abc";
            str += "efg";
 
 
            //(高效率 StringBuilder(可变字符串)在创建后 追加新的内容 是在原有内存中连续创建 提高效率)
            StringBuilder sb = new StringBuilder();
            //追加
            sb.Append("你好");
            sb.Append("吃饭了么");
            Console.WriteLine(sb.ToString());
              //插入
            sb.Insert(0, "abc", 2);
            Console.WriteLine(sb.ToString());
            //移除
            sb.Remove(0, 2);
            Console.WriteLine(sb.ToString());
            //清空
            sb.Clear();
            Console.WriteLine(sb.ToString());

格式化字符串

含义:用 { } 来表示,在 { } 内填写所占的位的序号,从0开始

            string name = "可乐";
            int age = 3;
            Console.WriteLine("{0}今年{1}岁",name,age);
格式化标识符
字母 含义
C或c Currency 货币格式
D或d Decimal 十进制格式(十进制整数,不要和.Net的Decimal数据类型混淆了)
E或e Exponent 指数格式
F或f Fixed point 固定精度格式
G或g General 常用格式
N或n 用逗号分割千位的数字,比如1234将会被变成1,234
P或p Percentage 百分符号格式
R或r Round-trip 圆整(只用于浮点数)保证一个数字被转化成字符串以后可以再被转回成同样的数字
X或x Hex 16进制格式
static void Main()   
         {
                   int i=12345;
                   Console.WriteLine("{0:C}",i);   //货币
                   Console.WriteLine("{0:D}",i);   //十进制数
                   Console.WriteLine("{0:E}",i);    //科学技术法
                   Console.WriteLine("{0:F}",i);   // 浮点数表示法
                   Console.WriteLine("{0:G}",i);   //G或g General 常用格式
                   Console.WriteLine("{0:N}",i);   //N或n 用逗号分割千位的数字
 
                   精度控制标识控制了有效数字的个数或者十进制数小数的位数
                    例如{0:C5}   C 代表类型  5代表精度
    
                    Console.WriteLine("{0:C5}", i); // ¥123,456.00
                    Console.WriteLine("{0:D5}", i); // 123456
                    Console.WriteLine("{0:E5}", i); // 1.23456E+005
                    Console.WriteLine("{0:F5}", i); // 123456.00000
                    Console.WriteLine("{0:G5}", i); // 1.23456E5
                    Console.WriteLine("{0:N5}", i); // 123,456.00000
                    Console.WriteLine("{0:P5}", i); // 12,345,600.00000 %
                    Console.WriteLine("{0:X5}", i); // 1E240
            
         }
 
时间格式化符号
d MM/dd/yyyy ShortDatePattern(短日期模式)
D dddd,MMMM dd,yyyy LongDatePattern(长日期模式)
F dddd,MMMM dd,yyyy HH:mm Full date and time (long date and short time)(全日期和时间模式)
F dddd,MMMM dd,yyyy HH:mm:ss FullDateTimePattern (long date and long time)(长日期和长时间)
G MM/dd/yyyy HH:mm General (short date and short time)(通用模式,短日期和短时间)
G MM/dd/yyyy HH:mm:ss General (short date and long time)(通用模式,短日期和长时间)
M,M MMMM dd MonthDayPattern(月天模式)
r,R ddd,dd MMM yyyy,HH':'mm':'ss 'GMT' RFC1123Pattern (RFC1123模式)
S yyyy-MM-dd HH:mm:ss SortableDateTimePattern (conforms to ISO 8601) using local time(使用本地时间的可排序模式)
T HH:mm ShortTimePattern (短时间模式)
T HH:mm:ss LongTimePattern(长时间模式)
U yyyy-MM-dd HH:mm:ss UniversalSortable-DateTimePattern (conforms to ISO 8601) using universal time(通用可排序模式)
U dddd,MMMM dd,yyyy,HH:mm:ss UniversalSortable-DateTimePattern(通用可排序模式)
y,Y MMMM,yyyy YearMonthPattern(年月模式)
static void Main()   
         {
                   Console.WriteLine("{0:D}",DateTime.Now);   //输出到天
                   Console.WriteLine("{0:y}",DateTime.Now);   //输出到月
                   Console.WriteLine("{0:m}",DateTime.Now);    //取出是那个月
                   Console.WriteLine("{0:T}",DateTime.Now);   // 取长时间到秒
                   Console.WriteLine("{0:t}",DateTime.Now);   //取短时间到分
                   Console.WriteLine("{0:tt}",DateTime.Now);   //取出是上午还是下午
                   Console.WriteLine("{0:yyyy-MM-dd HH:mm:ss}", DateTime.Now); 
                  Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));    
            
         }

模版字符串 $"{变量1},{变量2}"

            string name = "可乐";
            int age = 3;
            Console.WriteLine($"{name}今年{age}岁");

一、概述

一、关于类与对象

1、为什么要学习面向对象编程

答:面向过程编程,很难解决复杂业务逻辑和适应业务需求的变化。面向对象能够将程序很好的“模块化设计”,清晰的“分层组合”,方便的“业务扩展”。

2.从生活中的“类”转换到程序中的“类”

答:生活中很多东西都可以归为一个类。人:(男人、女人)

软件中的类,是为了处理相关数据。

4、类的规范(组成)

访问修饰符        class        类的名称

{

成员变量

        //字段部分

成员函数

        //属性部分

        //方法部分

}

1.访问修饰符:默认是internal(内部的)也可以定义为public

2.类的名字:使用大驼峰命名法(首字母大写)

3.类可以只有属性、只有方法、也可以属性、方法全部都有

什么是字段

成员变量(字段)

(1)字段是类型的成员,也称为成员变量 在类中字段也可以叫全局变量 在整个类中可以使用

(2)字段是定义在类中方法之外的 局部变量是定义在方法内部的

(3)字段的格式:访问修饰符(默认访问修饰符 private)数据类型  字段名,字段的访问修饰符:学过的修饰符字段都能使用

(4)字段是有默认值的 值类型默认值为0 引用类型默认值为null  局部变量没有默认值

(5)在一个类中  不能重复定义字段  但是允许定义相同名字的字段和局部变量 使用规则:就近原则

(6)字段的命名规则  _+小驼峰  保持和系统框架中的字段名字一致

(7)字段包含 静态字段和(非静态字段实例字段)

(8)const描述的字段 不能使用 static 原因 const描述的字段  本质就是包含静态的含义

(9)readonly描述的字段  可以使用static  可以在定义字段时赋值或者在其构造函数中赋值

(10)字段使用public 可以像方法一样调用        private字段 不能在类的外部使用

(11)一般使用字段时 都使用private的  为了内部的字段不暴露给其他类

但是使用private后 字段的灵活消失,使用类的成员-属性 来解决 字段灵活性的问题

(12)实例字段 实例字段属于每个对象 随着new对象的创建而创建

(13)静态字段 在类加载的时候创建 且只创建一次

三、对象的实例化

如何对象的实例化        使用new关键字 new 开辟内存空间为对应类的对象        (内存保存的是实例字段和实例方法和实例属性)

实例化一个对象语法是:

类名 对象名 = new 类名()

属性 和字段的关系


属性 和字段的关系

1.属性是类的成员函数

2.属性其实是外界访问私有字段的入口

3.属性本质就是方法  一个属性可以分别有一个set  和 get 方法组成。(或者称为访问器)

4.属性的名字用大驼峰命名  一般和对应的私有字段名字保持一致

5.属性的扩展 --- 增加字段的业务判断逻辑。

属性的基本格式

public string Code

{

get

{

return code;

}

set

{

code=value;

}

}

三、属性(Propety)

1、使用ILDasm反汇编工具发现get和set其实是两个办法,并且每一个属性都有对应的私有字段。

2.断电观察get和set发现,当我们给属性赋值的时候,其实是调用set方法,给对应的私有字段赋值,当读取属性值的时候,其实是调用了get方法,从对应的私有字段里面把值取出来。

属性:本身其实并没有保存数据,数据是保存到属性对用的私有字段中。

属性是为了更好的实现需求的变化的拓展,从而让一个属性可以实现多样的需求!

3.属性的拓展

【1】增加业务判断逻辑

  private int _test;
        public int Test
        {   
            set {
                if (value > 100)
                {
 
                    _test = 100;
                }
                else { 
                     _test = value;
                 }
            }
            get {
                return _test;
            } }

【2】设置只读字段功能

  private int _test =10;
       
        public int Test
        {   
            get {
                return _test;
            } }

【3】设置只读业务逻辑。(可以没有私有字段)

  public string Number  只读
        {
            get {
                string name = "zhangsan";
                return name;
            }  
           
        }

5.属性和字段对比

【1】字段,又称为“成员变量”

第一、目的:字段是为类的内部方法,或者方法之间传递数据使用,强调对内使用。

第二、修饰:字段一般用private修饰,很少用public。

第三、读写:字段可以读写均可,也可以用readonly限制为只读,但是不能添加业务逻辑。

【2】属性

第一、目的:属性是对外提供数据访问、本身不保存数据,强调对外使用。

第二、修饰:属性都是public,从来不用private。

第三、读写:属性可以轻松的实现单独读写控制,并且可以添加任意需要的业务逻辑。

   public int Test { get; set; } 可读可写
    

结论:开发中,只要对外使用数据,都用属性,即使没有任何拓展业务,我也不建议使用public类型的字段(强烈建议)。过多使用public类型的字段,会显得你不专业。

6.属性使用的新特性扩展(4.6或以上版本)

【1】属性直接初始化

public string StrNumber { get; set; } = "属性直接初始化";

【2】属性表达式

public string StrNumber2 { get => "属性表达式"; }
        public string StrNumber3 => "属性表达式";

7.对象类型的属性使用

总结:类本身就是一种数据类型(引用类型)所以,类中的属性或者变量(成员变量、局部变量)也可以是类类型(对象类型)

什么是方法

回顾以前内容

方法--构造函数

构造函数

1.本质就是方法

2.作用 类创建对象时 使用的特殊方法

3.类默认存在构造函数

4.构造函数的名字  一定要和类名相同

5.如果只是创建对象  直接使用默认的构造函数即可,如果想要扩展功能就要自己重新写构造函数

6.构造函数没有返回类型,它可以带参数,也可以不带参数

7.构造函数自己定义时,会覆盖系统默认的        自己定义构造函数原因:系统默认的功能无法满足需求

8.一般  会把所有实例成员  作为  构造函数的参数来定义  减少初始化对象后的  赋值过程

9.构造函数分为公有实例构造函数、私有实例构造函数和静态构造函数

10.实例构造一般使用public

11.私有构造函数使用private  不希望其他类  创建自身的对象时(没有实例成员时)

12.静态构造函数  默认系统会自带  在类创建时  用来初始化  所有的  静态成员  系统调用即可

13.静态构造函数既没有访问修饰符,也没有参数

14.无参数的实例构造函数可以与静态构造函数共存。尽管参数列表相同,但一个属于类,一个属于实例,所以不会冲突

   public class MyClass1 
    {
 
 
        /*
         私有构造函数可用于阻止外部创建类的实例 
         如果内部调回构造函数  还是可以创建对象  
         如果想要一个类 真正的没有对象创建  使用静态类
         */
        private static int _age;
        private static string _name;
 
        private MyClass1() {
            _age = 10;
            _name = "张三";
        }
 
        public static MyClass1 Create()
        {
 
            MyClass1 myClass1 = new MyClass1();
            return myClass1;
 
        }
 
} 

静态类

1.使用static描述的类

2.不能创建实例对象  也不能定义实例对象  只能定义静态相关成员

3.制作工具类时  可以使用

4.私有构造函数  限制了外部创建对象  静态类任何地方无法创建对象  没有提供实例构造函数有静态构造函数

5.静态类  无法被继承

//静态类  一般用于工具类 
    public static class MyClass2
    {
 
        //静态类中无法创建构造函数
        // public MyClass2() { }
        //静态类中的所有成员为静态
        private static int _age;
        private static string _name;
        public static string Name { set { _name = value; } get { return _name; }  }
        public static int Age { set { _age = value; } get { return _age; } }
 
        public static void MyClass2StaticMothod()
        {
 
            Console.WriteLine("MyClass2StaticMothod");
 
        }
 
    }

析构函数:

垃圾回收程序最终销毁对象之前调用的方法,该方法称为析构函数

  1. 析构函数通常形式如下:
  2. ~类名()
  3. {
  4.  }

析构函数的声明类似构造函数,除了在析构函数开头要使用“~”,另外要注意,析构函数,没有返回值,且不带任何参数。

析构函数的功能是用来释放一个对象的2.在对象删除前,用它来做一些清理工作,它与构造函数的功能正好相反。

什么是垃圾回收

在编写程序时,会产生很多的数据  比如:int String 变量,这些数据都存储在内存里,如果不合理的管理他们,就回内存溢出导致程序崩溃

C#内置了自动垃圾回收GC,在编写代码是可以不需要担心内存溢出的问题  变量失去引用后 GC会帮我们自动回收

什么样子的对象才会被回收?

1.GC 只会回收 的内存,而 值类型在 栈 中的使用完后马上就回给释放,并不需要 GC 进行处理,

2.堆中的没有被引用或者null的对象才会被回收,会调用析构函数通知程序 对象将要释放

3.静态的成员  会在程序结束后销毁。

什么时候进行垃圾回收?

什么时候回收这些都由操作系统决定,一般不需要进行理会全由系统调用,明确如有特殊的情况的需要进行释放  也可以强制的垃圾回收

 
namespace ConsoleApp1
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Test test = new Test();
            test = null;
            //强制开启回收
            GC.Collect();
            Console.ReadKey();
        }
    }
 
    public class Test {
        public int a;
        ~Test() {
            Console.WriteLine("ZHIXINGLE");
        }
 
   }

C#封装,继承,多态

面向对象特性:封装、继承、多态

三个特性主要重要目标:重用性(安全性)、灵活性和扩展性。

一、封装

什么是封装? 

将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的公共属性

来实现对隐藏信息的操作和访问。

封装可以通过以下方式实现:

属性(Property):通过Get和Set方法实现对数据的读写操作,并可以在进行数据读写是添加自定义的逻辑。在C#中,属性可以用于将实例变量封装到类中

访问修饰符:C#中有四种访问修饰符:public、private、protected和internal。这些访问修饰符可用于控制类中数据和方法的访问权限

方法:实现细节可以隐藏起来并只暴露实现所需的最小接口。这样可以保证类内部细节安全,并且仅在类的外部提供必要的接口

二、继承

什么是继承?

继承的作用:解决类与类直接  属性或者方法重复的问题

1.一个类继承另一个类  其中被继承的类(父类  超类  基类)        继承的类(子类  派生类)

2.继承的格式  A类(子类):B类(父类)

3.继承关系建立后  子类拥有父类的成员  反之父类不继承子类成员。父类私有成员  子类无法使用

4.一个父类可以同时被多个子类继承        子类可以间接继承父类

5.object是所有类的父亲  如果一个类  没有明确继承关系  默认继承与object类

6.C#中类与类之间是单继承关系(子类只能同时继承一个父类)        林勇接口实现多继承(后续讲)

7.创建子类对象时,系统默认先调用父类构造方法,然后再调用子类构造方法

8.当父类有有参构造方法是,必须提供一个无参构造函数  供子类调用

9.子类在调用其有参函数或者无参函数时,默认调用父类的  无参构造函数

如果想要调用父类有参构造函数  使用在子类构造函数后添加:base(参数名)

10.覆盖,在子类中写一个和基类一样名字(参数不同也算)的非虚函数,会让基类中的函数被隐藏,编译后会提示要求使用New 关键字

多态

什么是多态?

即一个接口,多个功能        同一种操作作用于不同的对象,可以有不同的解释,产生不同的执行效果

包含:

重写        抽象类  接口  重载

重载

在一个类中或者子类中函数名相同,参数类型或者顺序不同构成重载,与返回类型无关

重写:

在子类和父类中,子类中的方法名称和父类方法名称相同,参数相同

使用关键字  virtual  ,将父类的方法标记为虚方法,用  override  关键字,虚方法可以被子类重写

 public class Person
    {
        private string _name;
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
 
        public Person(string  name)
        {
            this.Name = name;
        }
 
        public virtual void SayHello()
        {
            Console.WriteLine("我是人类");
        }
    }
 
    public class Chinese:Person
    {
        public Chinese(string name)
            :base(name)
        {
 
        }
 
        public override void SayHello()
        {
            Console.WriteLine("我是中国人,我叫{0}", this.Name);
        }
    }
this
  • 当前类的对象
  • 静态成员方法不能使用this关键字,this关键字只能在实例构造函数、实例方法或实例访问器中使用

base

  • base关键字用于从派生类中访问基类的成员;
  • 派生类对象调用基类构造函数;
  • 调用基类上已被重写的方法
  • 不能从静态方法中使用base关键字,base关键字只能在实例构造函数、实例方法或实例访问器中使用

抽象类

//抽象类

1.关键字  absract

2.不能被实例化        不能创建对象

3.普通类和抽象类都可以继承抽象类,在另一层面上讲也可以说普通类相当于抽象类的多态

4.抽象类可以包括抽象方法和抽象属性,但是不能定义抽象字段,或者能定义普通方法属性字段

5.普通类继承了具有抽下个成员的  抽象类  必须在其内部重写抽象的抽象成员(使用override)

6.静态成员不能定义为抽象

用简单的话来说抽象类的功能就是:我是师傅(抽象类),你要是跟了(继承)师傅,你就必须得会干什么

例如:师傅会打人,那你也必须会打人,但你是轻轻的打,还是狠狠的打,你自己决定,但你必须得会打人。

类 DerivedClass 派生自抽象类 BaseClass。 抽象类包含抽象方法 AbstractMethod,以及两个抽象属性 X 和 Y
abstract class BaseClass  
{
    protected int _x = 100;
    protected int _y = 150;
    public abstract void AbstractMethod();   // Abstract method
    public abstract int X    { get; }
    public abstract int Y    { get; }
}
 
class DerivedClass : BaseClass
{
    public override void AbstractMethod()
    {
        _x++;
        _y++;
    }
 
    public override int X   // overriding property
    {
        get
        {
            return _x + 10;
        }
    }
 
    public override int Y   // overriding property
    {
        get
        {
            return _y + 10;
        }
    }
 
    static void Main()
    {
        var o = new DerivedClass();
        o.AbstractMethod();
        Console.WriteLine($"x = {o.X}, y = {o.Y}");
    }
}

接口

含义

接口定义了所有类继承接口时应遵循的语法合同,用接口可以是程序更加清晰和条理化  与抽象类功能相似

1.接口使用  interface 关键字声明,它与类的声明类似。接口默认是  public  的

2.接口只包含了成员的声明(方法  属性声明)

3.接口中只能包含方法、属性、索引器和事件的声明。不允许声明成员上的修饰符,即使是public都不行,因为接口成员是公有的,也不能声明为虚拟和静态的。如果需要修饰符,最好让实现类来声明。

4.一个类  可以继承多个接口(接口就是C#实现多继承的方式)

5.接口中定义的成员  需要继承类  来进行实现

6.接口也可以继承接口

接口和抽象类 区别和相同点

相同点:不能实例对象  都可以被继承 都可以给继承提供成员模版

不同点:接口只能有成员定义  抽象类  也可以包含成员的实现  接口可以实现多继承  抽象类只能单继承

密封类

1.密封类可以用来限制继承性

2.声明密封类时需要使用  sealed  关键字

3.密封类和普通类一样  都可以定义属性和方法

4.密封类不能作为基类被继承,但他可以继承别的类和接口

5.密封类可以实例化对象  系统中String 就是密封类

6.在密封类中不能声明受保护成员或虚成员

生成随机数

Random random = new Random();        得到的random就是一个随机数生成器,它可以用来生成随机数。

int Next(int minValue, int maxValue);
  这个方法能指定随机数的生成范围,左闭右开区间,即生成的数能包含minValue,不包含maxValue。可以包含负数。但是maxValue的值不能大于minValue的值,否则运行时会抛出异常。

int Next(int maxValue);
  这个方法指定随机数的最大值(不包含maxValue),并且它也只能生成非负整数,与Next(0, maxValue)是一个道理,如果传入的maxValue为负数,那么运行时抛出异常,如果maxValue的值为0或1,那么生成的随机数只能是0。

double NextDouble();
这个方法能返回一个大于或等于 0.0 且小于 1.0 的随机浮点数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值