《C# 语言入门详解(刘铁锰) - 学习笔记》

C# 学习笔记


文章目录

  • C# 学习笔记
  • 前言
  • 一、C# 语言及其特点
    • 1. C# 语言概念及其特点
    • 2. 认识.NET Framework & .NET Core
  • 二、C# 语法基础
    • 1. 关键字
    • 2. 类型
    • 3. 变量、常量与注释
    • 4. 表达式
    • 5. 数组、集合与字典
    • 6. 分支、循环语句
    • 7. 访问修饰符(封装)
    • 8. 方法(函数)
    • 9. 类和对象
  • 三、C# 语法进阶
    • 1. 委托(Delegate)
    • 2. 泛型(Generic)
    • 3. 接口(Interface)
  • 四、C# 补充
    • 1. 继承与多态
    • 2. 枚举类型与结构体
    • 3. Lambda表达 / Linq查询
  • 总结


前言

  • 本篇主要介绍C#的一些基础语法知识,如变量、数组、表达式、类、函数等;
  • 本篇后续会补充一些关于C#的一些不常见知识的基础概念

一、C# 语言及其特点

1. C# 语言概念及其特点

  • C# 是微软发布的一种面向对象的、运行于 .NET Framework.NET Core(完全开源,跨平台) 之上的高级程序设计语言;
  • C# 是一种安全的、稳定的、简单的、优雅的,由C和C++衍生出来的 面向对象 的编程语言。它在继承C和C++强大功能的同时去掉了一些它们的复杂特性;
  1. 面向对象与面向过程编程语言的区别:
  • 面向过程: 是一种以过程为中心的编程思想。它是一种基础的顺序思维方式,是以什么正在发生为主要目标进行编程,不同于面向对象的是谁在受影响;特性: 模块化、流程化;常见的 面向过程编程语言 有: C语言、COBOL 语言、Fortran语言 等。(优点: 性能比面向对象高,面向对象类调用需要实例化,消耗资源)
  • 面向对象: 是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物。它是直接把所有事物都当作独立的对象,处理问题过程中所思考的不再主要是怎样用数据结构来描述问题,而是直接考虑重现问题中各个对象之间的关系。(面向对象方法的基础实现中也包含面向过程思想);特性: 抽象 封装 继承 多态;常见的支持面向对象的编程语言有:C++ 语言、C# 语言、Java 语言、Python等。(优点: 有封装、继承、多态的特性,故而易维护、易复用、易扩展)

2. 认识.NET Framework & .NET Core

1. .NET与C#的关系:

  • .NET是平台;
  • C# 是平台所适用的对象,C# 只能运行在.NET 平台,但.NET平台还可适配其它对象,如C++,VB等。
    《C# 语言入门详解(刘铁锰) - 学习笔记》_第1张图片

2. .NET Framework 与 .NET Core的关系:

  • .Net Framework 历史要比 .Net Core 久一些。.Net Framework 的第一个版本大约在2002年前后推出的,而.Net Core的第一个版本,大约在2016年前后推出的,相差了将近14年的时间;
  • .Net Framework,只针对Windows平台,包含了Windows平台的所有特性;.Net Core 可以针对多个平台发布,但是.Net Core 无法包含.Net Framework的所有特性。但是.Net Core的跨平台特性可以方便的在多个平台上共享业务逻辑。

更多内容:详见.NET Framework 与 .NET Core 的区别与联系

二、C# 语法基础

1. 关键字

  • 关键字: 是预定义的保留标识符,对编译器有特殊意义。(除非前面有 @ 前缀,否则不能在程序中用作标识符。 例如,@if 是有效标识符,而 if 则不是,因为 if 是关键字。)
  • 常见的关键字:
    《C# 语言入门详解(刘铁锰) - 学习笔记》_第2张图片

2. 类型

C# 的类型一共分为两类,一种是值类型(Value Type),一类是引用类型(Reference)。

  • 值类型: 直接存储其值;值类型变量声明后,不管是否赋值,编译器为其分配内存;值类型的实例通常是在线程栈上分配的(静态分配),但在某些情形下可以存储在堆上。
  • 引用类型: 存储其对值的引用;引用类型声明一个类时,只在栈中分配一小片内存用于容纳一个地址,并没有为其分配堆上的内存空间。当使用 new 创建一个类的实例时,分配堆上的空间,并把堆上空间的地址保存到栈上分配的小片空间中;引用类型的对象总是在进程堆中分配(动态分配)
  • 常见的值类型: 数值类型(int、long、double、float等)、bool类型(true、false)、char类型、枚举类型(enum)、结构体类型(struct)、元组类型(tuple)、可空类型(null);(即:byte,short,int,long,float,double,decimal,char,bool 和 struct 统称为值类型。)
  • 常见的引用类型: 数组,用户定义的类、接口、委托,object,字符串。(即:string 和 class统称为引用类型。)

更多内容:详见C#的两种类据类型:值类型和引用类型

3. 变量、常量与注释

1. 变量与常量

  • 变量: 是一个供程序存储数据的盒子。在C# 中,每个变量都有一个特定的类型,不同类型的变量其内存大小也不尽相同;
  • 常量: 是固定值,程序执行期间不会改变。常量可以是任何基本数据类型,比如整数常量、浮点常量、字符常量或者字符串常量,还有枚举常量;(定义时,用const修饰符,如:public const int a = 1;)
  • 变量和常量是相对的:变量是指所存放的值是允许改变的,而常量表示存入的值不允许改变。
  1. C# 中提供的基本的值类型大致可以分为以下几类:
    《C# 语言入门详解(刘铁锰) - 学习笔记》_第3张图片
    C# 允许定义其他值类型的变量,比如 enum,也允许定义引用类型变量,比如 class。

2. 注释

  • 块注释: /* 注释内容 */
  • 单行注释: // 注释内容
  • 文档注释: /// 注释内容 (用于类、函数或方法的解释性注释方式)///
  • 注释快捷键: ctrl + k + c (注释);ctrl + k + u (取消注释)

4. 表达式

  • 表达式 = 操作数 + 运算符
  • 运算符: +、-、*、/、new;
  • 操作数: 文本、字段、局部变量、表达式;
  • 常用运算符优先级(从高到低排列)如下:
    《C# 语言入门详解(刘铁锰) - 学习笔记》_第4张图片
  1. 其他运算符
    《C# 语言入门详解(刘铁锰) - 学习笔记》_第5张图片

5. 数组、集合与字典

1. 数组

  • 定义: 数组是一组 相同类型 的数据;数组中的数据需要通过 数字索引 来访问;
  • 声明: 使用 关键字new 来声明;
    《C# 语言入门详解(刘铁锰) - 学习笔记》_第6张图片
  • 获取数据: 用索引获取数组内的元素时,索引从0开始,因此数组中最大的索引数字,比指定数组长度小1。
    《C# 语言入门详解(刘铁锰) - 学习笔记》_第7张图片
  • 优势: 数组在内存中是 连续存储的,所以它的 索引速度是非常的快,而且赋值与修改元素也很简单。
  • 劣势: 1. 数组的两个数据间 插入数据很麻烦;2. 在声明数组的时候,必须同时 指明数组的长度,数组的长度过长,会造成内存浪费,过短会造成数据溢出的错误。

2. 集合

  • 定义: 集合和数组类似,都是用于存放 一组值
  • ArrayList 集合: ArrayList 是.NET Framework提供的用于数据存储和检索的专用类;
    《C# 语言入门详解(刘铁锰) - 学习笔记》_第8张图片
  • ArrayList 的优势: 1. ArrayList 的大小是按照其中存储的数据来 动态扩充和收缩的;2. 在声明ArrayList对象时,不需要指定其长度 ;3. ArrayList可以 很方便的进行数据的添加、插入和移除。  (弥补了数组的劣势)
  • ArrayList 的劣势: 1. ArrayList在存储数据时,使用 object类型 进行存储的;2. ArrayList不是类型安全的,使用时可能会 出现不匹配 的错误;3.就算都有插入了同一类型的数据,但在使用的时候,我们也需要将它们转化为对应的原类型来处理;4.ArrayList的存储存在 装箱和拆箱 的操作,导致其性能低下。

※ 装箱与拆箱的概念:(装箱 与 拆箱 的过程会产生较多的性能损耗)

  • 装箱: 就是将,比如int类型或者string类型等不同的对象,通过 隐式赋值 赋给object 对象;
    在这里插入图片描述
  • 拆箱: 就是将object对象通过 显示转换 赋给int类型的变量。
    在这里插入图片描述
  • List 集合: 1. List 集合与 ArrayList 由于都继承了相同的 接口,故使用与 ArrayList相同;2. 在声明List 集合时,需要同时为其声明的List 集合内数据的 对象类型
    《C# 语言入门详解(刘铁锰) - 学习笔记》_第9张图片

※ 集合与数组小结:

  1. 集合与数组比较类似,都用于存放 一组值
  2. 集合中提供了特定的方法能直接操作集合中的数据,并提供了不同的集合类型来实现特定的功能;
  3. 集合简单来说,就是数组的升级版,他可以动态的对集合的长度(即集合内最大元素的个数)进行定义和维护;
  4. List泛型的好处指,通过允许指定 泛型类或方法 操作的 特定类型,减少类型 强制转换 的需要和运行时错误的可能性,泛型提供了类型安全,但没有增加开销。

3. 字典

  • 定义: 字典(Dictionary) 有 Key 和 Value,一个键只能对应一个值,一个值 可以对应多个 键;
  • 使用: 声明 Dictionary 字典的时候,需要同时为其声明 Dictionary 字典内 键与值 的类型;
    《C# 语言入门详解(刘铁锰) - 学习笔记》_第10张图片

6. 分支、循环语句

1. 分支语句:

  • if 语句:
if(/*判断语句*/)
{
    //代码
}
  • if else语句:
if(/*判断语句*/)
    //代码
else if(/*判断语句*/)
    //代码
else if(/*判断语句*/)
    //代码
else
    //代码
  • Switch语句:
switch (变量)
{
case:
    {
        //代码段
    }
    break;
case2:
    //代码句
    break;
default:
    {
        代码段
    }
    break;
}

2. 循环语句:

  • while循环:
while(condition)
{
   statement(s);	//代码块
}
  • for/foreach 循环: (foreach 用于迭代数组或集合的循环)
 for (int a = 10; a < 20; a = a + 1)
 {
    Console.WriteLine("a 的值: {0}", a);
 }
int[] fibarray = new int[] { 0, 1, 1, 2, 3, 5, 8, 13 };
foreach (int element in fibarray)
{
	System.Console.WriteLine(element);
}
  • do…while 循环:
 /* do 循环执行 */
do
{
	Console.WriteLine("a 的值: {0}", a);
	a = a + 1;
} while (a < 20);

7. 访问修饰符(封装)

  • 封装: 把一个或多个项目封闭在一个物理的或者逻辑的包中,在面向对象程序设计方法论中,封装是为了防止对实现细节的访问;
  • 实现: C# 封装根据具体的需要,设置使用者的访问权限,并通过 访问修饰符 来实现;
  • 访问修饰符: 定义了一个类成员的范围和可见性。
    《C# 语言入门详解(刘铁锰) - 学习笔记》_第11张图片

8. 方法(函数)

1. 定义方法:

<Access Specifier> <Return Type> <Method Name>(Parameter List)
{
   Method Body
}
  • Access Specifier:访问修饰符,这个决定了变量或方法对于另一个类的可见性;
  • Return type:返回类型,返回类型是方法返回的值的数据类型。如果方法不返回任何值,则返回类型为 void;
  • Method name:方法名称,是一个唯一的标识符,且是大小写敏感的,方法命名首字母大写
  • Parameter list:参数列表,使用圆括号括起来,该参数是用来传递和接收方法的数据;
  • Method body:方法主体。

2. 参数传递:

当调用带参数返回的方法时,需要向方法传递参数;C#中,有三种参数传递方式:值参数传递引用参数传递输出参数传递

  • 值参数传递: 形参发生改变时,不影响实参的值,保证实参数据安全;
using System;
namespace CalculatorApplication
{
   class NumberManipulator
   {
      public void swap(int x, int y)
      {
         int temp;
         
         temp = x; /* 保存 x 的值 */
         x = y;    /* 把 y 赋值给 x */
         y = temp; /* 把 temp 赋值给 y */
      }
     
      static void Main(string[] args)
      {
         NumberManipulator n = new NumberManipulator();
         /* 局部变量定义 */
         int a = 100;
         int b = 200;
         
         Console.WriteLine("在交换之前,a 的值: {0}", a);
         Console.WriteLine("在交换之前,b 的值: {0}", b);
         
         /* 调用函数来交换值 */
         n.swap(a, b);
         
         Console.WriteLine("在交换之后,a 的值: {0}", a);
         Console.WriteLine("在交换之后,b 的值: {0}", b);
         
         Console.ReadLine();
      }
   }
}

==>结果:(结果表明,即使在函数内改变了值,值也没有发生任何的变化。)
在交换之前,a 的值:100
在交换之前,b 的值:200
在交换之后,a 的值:100
在交换之后,b 的值:200
  • 引用参数传递(ref修饰): 传递的是变量内存地址,即形参发生改变时,实参也会发生改变;
namespace CalculatorApplication
{
   class NumberManipulator
   {
      public void swap(ref int x, ref int y)
      {
         int temp;

         temp = x; /* 保存 x 的值 */
         x = y;    /* 把 y 赋值给 x */
         y = temp; /* 把 temp 赋值给 y */
       }
   
      static void Main(string[] args)
      {
         NumberManipulator n = new NumberManipulator();
         /* 局部变量定义 */
         int a = 100;
         int b = 200;

         Console.WriteLine("在交换之前,a 的值: {0}", a);
         Console.WriteLine("在交换之前,b 的值: {0}", b);

         /* 调用函数来交换值 */
         n.swap(ref a, ref b);

         Console.WriteLine("在交换之后,a 的值: {0}", a);
         Console.WriteLine("在交换之后,b 的值: {0}", b);
 
         Console.ReadLine();

      }
   }
}

==>结果:(结果表明,swap 函数内的值改变了,且这个改变可以在 Main 函数中反映出来。)
在交换之前,a 的值:100
在交换之前,b 的值:200
在交换之后,a 的值:200
在交换之后,b 的值:100
  • 输出参数传递(out修饰): 可以返回多个值。(C#7.0,要获取多个返回值时,建议使用元组)
using System;

namespace CalculatorApplication
{
   class NumberManipulator
   {
      public void getValues(out int x, out int y )
      {
          Console.WriteLine("请输入第一个值: ");
          x = Convert.ToInt32(Console.ReadLine());
          Console.WriteLine("请输入第二个值: ");
          y = Convert.ToInt32(Console.ReadLine());
      }
   
      static void Main(string[] args)
      {
         NumberManipulator n = new NumberManipulator();
         /* 局部变量定义 */
         int a , b;
         
         /* 调用函数来获取值 */
         n.getValues(out a, out b);

         Console.WriteLine("在方法调用之后,a 的值: {0}", a);
         Console.WriteLine("在方法调用之后,b 的值: {0}", b);
         Console.ReadLine();
      }
   }
}

==>结果:(结果取决于用户输入)
请输入第一个值:
7
请输入第二个值:
8
在方法调用之后,a 的值: 7
在方法调用之后,b 的值: 8

※ 辨析:out 和 ref 的区别:

  • out 修饰的参数必须在方法内修改,ref可以修改也可以不修改;
  • out 在传入参数的时候,参数是局部变量的话,可以不用赋值;
  • ref 修饰的参数,在实参必须有初始值才能调用。(因为ref修饰的不一定会给它赋值)

9. 类和对象

类和对象是面向对象编程的两个核心概念。

  • 类: 是对一群具有 相同属性 或者 方法 的事物的统称,不能直接使用,用class声明;
  • 对象: 由类创造出来的一个具体存在,可以直接使用, 使用关键字 new 实例化。

※ 类与对象的关系:

  • 类是模板,对象是根据 类 这个模板创建出来的,应该是 先有类,再有对象
  • 类只有一个,而对象可以有很多个;(不同对象之间属性的具体方法可能各不相同)
  • 类中定义了什么 属性和方法,对象 中就有什么属性和方法,不可能多,也不可能少

三、C# 语法进阶

1. 委托(Delegate)

内容详见:《C# 语言入门详解(刘铁锰) - 学习笔记 - 委托》

2. 泛型(Generic)

内容详见:《C# 语言入门详解(刘铁锰) - 学习笔记 - 泛型》

3. 接口(Interface)

内容详见:《C# 语言入门详解(刘铁锰) - 学习笔记 - 接口与抽象类》

四、C# 补充

1. 继承与多态

内容详见:《C# 语言入门详解(刘铁锰) - 学习笔记 - 类的继承 之 重写与多态、密封类与密封方法》

2. 枚举类型与结构体

内容详见:《C# 语言入门详解(刘铁锰) - 学习笔记 - 枚举类型/结构体》

3. Lambda表达 / Linq查询

内容详见:《C# 语言入门详解(刘铁锰) - 学习笔记 - Lambda表达 / Linq查询》


总结

  • 未完待续,敬请期待… …

你可能感兴趣的:(学习笔记,c#)