总目录


文章目录

  • 总目录
  • 前言
  • 一、C#简述
    • 1 C#是什么?
    • 2 .Net平台
    • 3. C# 和.Net的关系
    • 4. 集成开发环境(IDE)
  • 二、控制台应用程序
    • 1. 常用代码
    • 2.注意事项
  • 三、基础语法
    • 1.编写C#代码注意事项
    • 2.C#注释
    • 2. 变量&标识符&关键字
    • 4. 变量,字段和属性的区别
    • 5.数据类型
      • 1、值类型
      • 2、引用类型
      • 3、指针类型
    • 6. 类型转换
      • 1、隐式转换
      • 2、显式转换
      • 3、装箱与拆箱
    • 7. 常量
    • 8. 运算符
      • 1、算数运算符
      • 2、关系运算符
      • 3、逻辑运算符
      • 4、位运算符
      • 5、赋值运算符
      • 6、其他运算符
      • 7、运算符优先级
    • 9. 流程控制语句
      • 1、选择结构
      • 2、循环(loop)结构
    • 10. 数组&字符串&结构体&枚举
    • 11. C#关键字之修饰符
      • 1、访问修饰符
      • 2、其他修饰符
    • 11. 方法
    • 12. 类
      • 1、类的基本内容
      • 2、构造函数
      • 3、析构函数(终结器)
      • 4、内部类
    • 13. 接口
    • 14. 接口和抽象类
  • 结语

前言

本文主要供自身复习使用,主要内容就是将C#基础知识进行大纲式针对性的梳理。


一、C#简述

1 C#是什么?

C# 是由微软(Microsoft)开发的一个简单的、现代的、通用的、面向对象的编程语言。

2 .Net平台

  • 1 .Net框架(.Net Framework)
    说到C#,那就必须说说.Net, C# 是 .Net 框架的一部分,且用于编写 .Net 应用程序。
    .Net Framework是一个平台,主要可以开发Windows 桌面程序和Web应用。.Net 框架由一个巨大的代码库组成,用于 C# 等客户端语言。

我们常见的.Net 框架的组件:

  • 公共语言运行库(Common Language Runtime - CLR)
  • .Net 框架类库(.Net Framework Class Library)
  • 公共语言规范(Common Language Specification)
  • 通用类型系统(Common Type System)
  • 元数据(Metadata)和组件(Assemblies)
  • Windows 窗体(Windows Forms)
  • ASP.Net 和 ASP.Net AJAX
  • ADO.Net
  • Windows 工作流基础(Windows Workflow Foundation - WF)
  • Windows 显示基础(Windows Presentation Foundation)
  • Windows 通信基础(Windows Communication Foundation - WCF)
  • LINQ
  • 2 .Net Core
    .Net Core是微软继.Net Framework之后推出的可以跨平台的平台,可以用来创建运行在mac、Linux上的应用程序

  • 3 .Net
    完成了对.Net Framework和.Net Core的整合,是一个全新的强大的跨平台的平台

3. C# 和.Net的关系

.net就像是大舞台,C#就是其中的一个演员,演员可以使用平台提供的话筒(wpf),用来唱歌(创建应用程序);也可以使用平台提供的舞池(web)跳舞(创建web应用),C#只可以在这个大舞台上展示,但是这个舞台除了可以提供C#这个演员展示,还可以提供C++、Visual Basic、Jscript、COBOL 等演员展示

4. 集成开发环境(IDE)

目前主要使用的是Visual Studio 2022 (VS)

二、控制台应用程序

1. 常用代码

控制台应用程序是入门级的应用程序,一般常用的代码如下:

//输出
Console.Write();
//换行输出
Console.WriteLine();
//以上代码主要用于在控制台输出信息//读取输入
Console.Read();
//读取当前行输入
Console.ReadLine();
//读取字符
Console.ReadKey();
//以上代码主要用于在控制读取输入的信息//接受用户输入的字符串,以换行结束
string s=Console.ReadLine();

2.注意事项

  • 控制台应用程序代码需要以Console.ReadLine()或Console.ReadKey()等结束,否则代码走完,控制台的窗体就会关闭

三、基础语法

1.编写C#代码注意事项

  • C#代码是区分大小写的
  • 所有的语句和表达式必须以分号(;)结尾。

2.C#注释

  • //表示单行注释
  • /* */ 表示多行注释

2. 变量&标识符&关键字

先看如下示例代码:

    class Rectangle{// 成员变量double length;double width;public double GetArea(){length = 3;width = 2;return length * width;}public void Display(){Console.WriteLine($"Length: {length}");Console.WriteLine($"Width: {width}");Console.WriteLine($"Area: {GetArea()}");}}
  • 变量:变量是类的属性或数据成员,用于存储数据。如上面案例代码中, length 和 width 就是成员变量
  • 标识符:标识符是用来识别类、变量、函数或任何其它用户定义的对象

标识符命名规则:

  • 标识符必须以字母、下划线或 @ 开头,后面可以跟一系列的字母、数字( 0 - 9 )、下划线( _ )、@。
  • 标识符中的第一个字符不能是数字。
  • 标识符必须不包含任何嵌入的空格或符号,比如 ? - +! # % ^ & * ( ) [ ] { } . ; : " ’ / \。
  • 标识符不能是 C# 关键字。除非它们有一个 @ 前缀。 例如,@if 是有效的标识符,但 if 不是,因为 if 是关键字。
  • 标识符必须区分大小写。大写字母和小写字母被认为是不同的字母。
  • 不能与C#的类库名称相同。

如上面的length、width、GetArea、Display 等变量或函数的名称都是标识符

  • 关键字:关键字是 C# 编译器预定义的保留字。这些关键字不能用作标识符,但是,如果您想使用这些关键字作为标识符,可以在关键字前面加上 @ 字符作为前缀。‘

4. 变量,字段和属性的区别

首先我们写一个示例代码:

    class UserInfo{private string _id;private string _name;public string Id{get { return _id; }set { _id = value; }}public string Name{get { return _name; }set { _name = value; }}}

上面的代码中:_id,_name 是字段,Id,Name 是属性,而_id,_name,Id,Name都是成员变量。

  • 字段和属性都是变量,只不过是为了区分和数据安全做出了区分。
  • 字段和属性是相对于类而言的,都是在类中定义的;而变量不局限在类中,可以定义在任何需要的地方
  • 字段一般使用在类的内部,只可在当前类内部访问,属性一般供外部类访问;
  • 字段一般来讲都是private,而属性则是对字段使用get和set 进行了封装,一般为public
  • 字段值可以用作ref、out参数,而属性不能

5.数据类型

在C#中,有以下几种类型:

  • 值类型
  • 引用类型
  • 指针类型(不常用)

1、值类型

值类型变量可以直接分配给一个值。它们是从类 System.ValueType 中派生的。值类型直接包含数据。
值类型又可分为:

分类 详情 备注
整型 byte short ushort int uint long ulong
浮点型 float double decimal decimal多用于金钱计算上
字符型 char 每个字符背后都对应着一个ascii码,“A”为65;“a”为97;“0”为 48
布尔型 bool true/false
可以为空的值类型 如 int? 值为 null 的其他所有值类型的扩展
结构体 struct
枚举 enum
元组值类型 形如 (double,int)t1=(1.1,2); 详见C#元组的使用

2、引用类型

引用类型不包含存储在变量中的实际数据,但它们包含对变量的引用。换句话说,它们指的是一个内存位置。使用多个变量时,引用类型可以指向一个内存位置。如果内存位置的数据是由一个变量改变的,其他变量会自动反映这种值的变化。内置的 引用类型有:object、dynamic 和 string。

分类 详情 备注
对象类型Object 对象(Object)类型 是 C# 通用类型系统(Common Type System - CTS)中所有数据类型的终极基类 数组,集合,用户定义的类、接口、委托,object,
动态类型Dynamic 您可以存储任何类型的值在动态数据类型变量中。这些变量的类型检查是在运行时发生的。 动态类型与对象类型相似,但是对象类型变量的类型检查是在编译时发生的,而动态类型变量的类型检查是在运行时发生的。
字符串类型String 字符串(String)类型 允许您给变量分配任何字符串值 这里需要注意的就是转义符的使用
  • string相关的还有如下一个问题:“\”的使用与扩展
运用 详情 备注
\ 输出特殊字符 使用在字符串中,使用\则可以输出“”和\ 等字符
\n 换行 使用在字符串中,输出的时候会自动换行
\t 制表符 使用在字符串中,输出的时候会自动对齐,隔开
\b 去掉上一个字符串 如果需要输出\b则需进行转义
  • @和\的使用
string path1 = "E:\\MyCode\\my-study";
string path2 = @"E:\MyCode\my-study";
Console.WriteLine($"path1:{path1}-------path2:{path2}");

由上可知,当前我们使用@进行字符串转义的话,我们可以避免使用“\”逐个的进行转移。

3、指针类型

指针类型变量存储另一种类型的内存地址。C# 中的指针与 C 或 C++ 中的指针有相同的功能。
声明指针类型的语法:type* identifier; 如:char* cptr; int* iptr;

6. 类型转换

类型转换就是将数据从一种类型转换为另一种类型,类型转换有两种形式:

1、隐式转换

这些转换是 C# 默认的以安全方式进行的转换, 不会导致数据丢失。将类型较小的数据存放到较大的变量中

2、显式转换

显式转换需要强制转换运算符,而且强制转换会造成数据丢失。将类型较大的数据存放在较小的变量中

案例代码如下:

        static void Main(string[] args){int num1 = 1;long num2 = num1;//隐式类型转换//强制类型转换:(数据类型)数据double num3 = 3.56;int num4 = (int)num3;int num5 = Convert.ToInt32(num3);//Convert 对象转换Console.WriteLine($"3.56强制转换后的结果:{num4}\n3.56使用Convert对象转换的结果:{num5}");//3.56强制转换后的结果:3//3.56使用Convert对象转换的结果:4Console.ReadLine();}

由上面的代码案例可以清晰的了解数据的转换,另外还可从上面的案例可知,显式转换存在两种形式,一种是强制类型转换,这种方式对于浮点型不会进行四舍五入,直接将小数点后面的数据舍弃;另一种是使用Convert对象进行转换,这种方式则会对浮点型数据进行四舍五入的计算,然后进行转换。

3、装箱与拆箱

  • 装箱是将值类型转换为引用类型; 拆箱就是将引用类型转换为值类型

示例代码如下:

        static void Main(string[] args){//装箱:值类型转换为引用类型int num = 111;object obj = num;Console.WriteLine($"obj = {obj}"); //obj = 111//拆箱:引用类型转换为值类型int nnum = 222;object oobj=nnum;int result = (int)oobj;Console.WriteLine($"result = {result}");//result = 222//【注意】:被装过箱的对象才能被拆箱}

我们知道平常写代码的时候要尽量的避免装箱和拆箱,但是为什么要这样呢?要搞清白这些啊,那就必须知道,什么是堆和栈以及装箱和拆箱的过程

  • 堆和栈

堆栈简单来说,就是计算机存储数据的一个数据模型。
模型分为堆和栈两部分,栈中主要存放一些简单结构的数据和复杂数据的索引,堆中存储复杂数据结构的数据内容。简单的数据结构就是值类型,复杂数据结构就是引用类型

  • 装箱和拆箱的过程

装箱过程:
①先在堆上为新生成的引用对象分配内存,
②然后将值类型的数据copy到刚分配的内存中,
③最后返回内存的地址(引用对象在栈中会存储这个内存的地址,相当于数据的索引)。
在装箱的过程中分配内存和数据复制都是消耗效能的操作

拆箱过程:
①先检查当前的引用类型数据是否可以转换为目标值类型数据
(例如,string str="123"可以转换为Int ,而str="asd"不可以)
②复制堆中的数据的值并将复制的值放到目标数据所在的存储位置
拆箱过程有类型检查和复制数据两个操作,其中复制数据耗费性能

由此我们可知,装箱和拆箱比较影响程序运行的性能,所以我们需要尽量的避免此类操作!

7. 常量

常量是固定值,程序执行期间不会改变。常量可以是任何基本数据类型,比如整数常量、浮点常量、字符常量或者字符串常量,还有枚举常量。
常量可以被当作常规的变量,只是它们的值在定义后不能被修改。

详情可见:C#常量,这里重点说一下定义常量,常量是使用const关键字来定义的,示例如下:

 public const string URL = "www.xxxx.com";public const int num = 999;

常量扩展:
静态常量(编译时常量)const 和动态常量(运行时常量)readonly
静态常量在编译时就确定了值,必须在声明时就进行初始化且之后不能进行更改,可在类和方法中定义。定义方法如下:

const double a=3.14;// 正确声明常量的方法
const int b;         // 错误,没有初始化

动态常量在运行时确定值,只能在声明时或构造函数中初始化,只能在类中定义。定义方法如下:

class Program
{readonly int a=1;  // 声明时初始化readonly int b;    // 构造函数中初始化Program(){b=2;}static void Main(){}
}

8. 运算符

运算符是一种告诉编译器执行特定的数学或逻辑操作的符号。C# 有丰富的内置运算符,分类如下:

  • 算术运算符
  • 关系运算符
  • 逻辑运算符
  • 位运算符
  • 赋值运算符
  • 其他运算符

1、算数运算符

运算符 描述 备注
+ 将两个操作数相加 当字符串和数值类使用 + 则是拼接字符串
- 将两个操作数相减
* 将两个操作数相乘
/ 将两个操作数相除 当两个操作数均为整数的时候,结果取商;
当两边有一个为浮点型的时候,做精确运算
% 模运算符,整除后取余数 如 21%10=1
++ 自增运算符,整数值增加1 注意:当自增运算符在前,则先自增,然后再使用自增后的赋值;
当自增运算符在后,则先赋值,然后再自增
- - 自减运算符,整数值减去1 同上

注意:在char类型参与到算数运算时,会自动转化为ascii码10进制的值参与运算

class Program{static void Main(string[] args){int a = 1;int b;// a++ 先赋值再进行自增运算b = a++;Console.WriteLine("a = {0}", a);Console.WriteLine("b = {0}", b);Console.ReadLine();//结果a=2,b=1// ++a 先进行自增运算再赋值a = 1; // 重新初始化 ab = ++a;Console.WriteLine("a = {0}", a);Console.WriteLine("b = {0}", b);Console.ReadLine();//结果a=2,b=2// a-- 先赋值再进行自减运算a = 1;  // 重新初始化 ab= a--;Console.WriteLine("a = {0}", a);Console.WriteLine("b = {0}", b);Console.ReadLine();//结果a=0,b=1// --a 先进行自减运算再赋值a = 1;  // 重新初始化 ab= --a;Console.WriteLine("a = {0}", a);Console.WriteLine("b = {0}", b);Console.ReadLine();//结果a=0,b=0}}

2、关系运算符

运算符 描述
== 检查两个操作数的值是否相等,如果相等则条件为真
!= 检查两个操作数的值是否相等,如果不相等则条件为真。
> 检查左操作数的值是否大于右操作数的值,如果是则条件为真
< 检查左操作数的值是否小于右操作数的值,如果是则条件为真。
>= 检查左操作数的值是否大于或等于右操作数的值,如果是则条件为真。
<= 检查左操作数的值是否小于或等于右操作数的值,如果是则条件为真。

注:关系运算符的运算结果均是bool ,常运用于判断语句中

3、逻辑运算符

运算符 描述
|| 或 运算符,当两个操作数均为false ,则结果为false,其余均为true
&& 与 运算符, 当两个操作数均为true,则结果为true,其余均为false
! 非 运算符,取反

注:
① 逻辑运算符的短路效果,当运算符的左边的结果对整个表达式结果起了决定性的作用的时候,运算符右边的表达式就不会运行。

如:当&&运算符左边为false的时候,此时无论运算符右边是什么,结果都为false,那么右边表达式就不会运行。

② 当单独使用| 和& 就不会产生短路的效果,即使左边已经起了决定性作用,右边仍会运行。

4、位运算符

运算符 描述
& 与 位运算符,当两个操作数均为1 ,则结果为1,其余均为0
| 或 位运算符, 当两个操作数均为0,则结果为0,其余均为1
^ 异或 运算符,当两个操作均为0或1,则结果为0,其余结果为1
~ 按位取反 运算符,具有翻转位的效果,可将0变1,1变0
<< 二进制左移运算符。左操作数的值向左移动右操作数的位数
>> 二进制右移运算符。左操作数的值向右移动右操作数指定的位数。

辅助理解的案例代码如下:

     static void Main(string[] args){//60 和13 转换位二进制分别是111100 和 1101 ,不足8位【前面】使用0补足int a = 60;            /* 60 = 0011 1100 */int b = 13;            /* 13 = 0000 1101 */int c = 0;c = a & b;// a      0011 1100// b      0000 1101//-----------------   根据&运算符规则:只有均为1的时候,结果才为1,否则均为0// c      0000 1100===>转换为十进制 则是12Console.WriteLine("Line 1 - c 的值是 {0}", c);c = a | b;// a      0011 1100// b      0000 1101//-----------------   根据|运算符规则:只有均为0的时候,结果才为0,否则均为1// c      0011 1101===>转换为十进制 则是61Console.WriteLine("Line 2 - c 的值是 {0}", c);c = a ^ b;// a      0011 1100// b      0000 1101//-----------------   根据^运算符规则:只有均为0或1的时候,结果才为0,否则均为1// c      0011 0001===>转换为十进制 则是49Console.WriteLine("Line 3 - c 的值是 {0}", c);c = ~a;               /*-61 = 1100 0011 */// a      0011 1100//取反-----------------   根据~运算符规则:将0变1 ,1变0// c      1100 0011===>转换为十进制 则是-61Console.WriteLine("Line 4 - c 的值是 {0}", c);c = a << 2;   // a      0011 1100//左移-----------------  0011 1100 向左移动两位则将前面两位00 移掉了,然后后面补足两位00// c      1111 0000===>转换为十进制 则是240Console.WriteLine("Line 5 - c 的值是 {0}", c);c = a >> 2;// a      0011 1100//右移-----------------  0011 1100 向右移动两位则将后面两位00 移掉了,然后前面补足两位00// c      0000 1111===>转换为十进制 则是15Console.WriteLine("Line 6 - c 的值是 {0}", c);Console.ReadLine();}

5、赋值运算符

6、其他运算符

这里包括有 is ,as ,typeof 等运算符.

  • is 运算符检查表达式的结果是否与给定的类型相匹配。
 public class Base { }public class Derived : Base { }class Program{static void Main(string[] args){// 基类和派生类 之间的is 类型检查var b = new Base();Console.WriteLine(b is Base);//TrueConsole.WriteLine(b is Derived);//Falsevar d = new Derived();Console.WriteLine(d is Base);//TrueConsole.WriteLine(d is Derived);//True//派生类可以是基类类型,is 检查返回True //基类不可以是派生类的类型;//这个道理就像:兔子,狮子,小狗都可以用动物称呼,但是说所有动物都是小狗那就不行了//is 运算符将考虑装箱和取消装箱转换,但不会考虑数值转换int i = 27;object iBoxed = i;Console.WriteLine(iBoxed is int);  // output: TrueConsole.WriteLine(iBoxed is long);  // output: Falseobject obj = 99.9;if (obj is string s){Console.WriteLine("结果:"+s);}if (obj is double score){Console.WriteLine("结果:" + score);}//以上案例说明:is的本质是 检查类型,通过检查返回True,反之,False//检查是否为nullif (obj is null){Console.WriteLine("**********");}//检查是否为非nullif (obj is not null){Console.WriteLine("**********");}Console.ReadLine();}}
  • as运算符将表达式显式转换为给定类型(如果其运行时类型与该类型兼容)
    如果无法进行转换,则 as 运算符返回 null(as不能用于值类型,值类型不能为null)。
    与强制转换表达式(形如(int)12) 不同,as 运算符永远不会引发异常。
         object obj1 = "121212";int le1 = (obj1 as string).Length;//可以转换object obj2 = null;int le2 = (obj2 as string).Length;//可以转换,但是由于转换后值为null,因此运行时会报错object obj3 = new object();string sr = obj as string;if (sr == null){Console.WriteLine("转换失败");}else{ Console.WriteLine("转换成功");}//使用 as 转换的时候需要注意,转为结果为null的情况//is 对比 as if (obj3 is string str3){Console.WriteLine($"转换成功{str3}");}else{Console.WriteLine($"转换失败");}
  • typeof运算符获取某个类型的 System.Type 实例。
public class Animal { }public class Giraffe : Animal { }public static class TypeOfExample
{public static void Main(){object b = new Giraffe();Console.WriteLine(b is Animal);  // output: TrueConsole.WriteLine(b.GetType() == typeof(Animal));  // output: FalseConsole.WriteLine(b is Giraffe);  // output: TrueConsole.WriteLine(b.GetType() == typeof(Giraffe));  // output: True}
}

7、运算符优先级

  • 优先级大体上是:算数运算符> 关系运算符>逻辑运算符>赋值运算符
  • 算数运算中:当有括号时,先计算括号内的,然后前运算符,再乘除模,再加减,最后后运算符
  • 逻辑运算符中:当同时出现或运算符和与运算符,先计算与 运算符,然后计算或运算符

辅助理解的案例代码如下:

//算术运算符和赋值运算符的优先级:
int a = 10, b = 5, c = 2;
a += b * c;               // 先计算乘法,再执行加法赋值
Console.WriteLine(a);       // 输出20//逻辑运算符的优先级:
bool a = true, b = false, c = true;
bool result = a || b && c;  // 先计算与运算,再计算或运算
Console.WriteLine(result);  // 输出true//条件运算符的优先级:
int a = 10, b = 5;
string result = a > b ? "a大于b" : "a不大于b";  // 先判断大小关系,再执行条件语句
Console.WriteLine(result);  // 输出"a大于b"

9. 流程控制语句

1、选择结构

  • if else
            //第一种:只有if,没有elseif (num>15){//...}//第二种:有if elseif (num > 15){//...}else{//...}//第三种:多种判断if  else if ...elseif (num>15){//...}else if (num>0){//...}else{//...}
  • switch

一个 switch 语句允许测试一个变量等于多个值时的情况,算是if else 在某一层面上的进阶版。

switch 语句中的表达式 必须是一个整型或枚举类型,或者是一个 class 类型,其中 class 有一个单一的转换函数将其转换为整型或枚举类型

运用switch的典型案例:输入年月,得出该月的天数

        static void Main(string[] args){Console.WriteLine("请输入年份:");int year = Convert.ToInt32(Console.ReadLine());Console.WriteLine("请输入月份:");int month = Convert.ToInt32(Console.ReadLine());int day = 0;//定义天数switch (month){//大月case 1:case 3:case 5:case 7:case 8:case 10: case 12: day = 31; break;//小月case 4: case 6: case 9: case 11: day = 30; break;case 2://主要是需要对二月进行判断,是否是闰月if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0){//满足条件,则为闰年中的闰月,输出29天day = 29;break;}else{day = 28;break;}default:Console.WriteLine("请输入正确的月份数字!");break;}Console.WriteLine($"{year}年{month}月有{day}天");Console.ReadLine();}
  • 三元运算符?:

x?y:z 表示如果表达式 x 为 true,则返回 y;如果 x 为 false,则返回 z,是 if{}else{} 的简单形式。

     static void Main(string[] args){int a=11; int b=22;int c = a > b ? a : b;Console.WriteLine($"c={c}");Console.ReadLine();//结果: c=22}

2、循环(loop)结构

循环语句允许我们多次执行一个语句或语句组。

  • for

简单使用案例:

         for (int i = 0; i < 10; i++){Console.WriteLine($"i={i}");}Console.ReadLine();

当我们需要无限循环的时候,只需要如下使用:

         //将各项条件均省略,程序会默认为true,一直运行for (; ;){Console.WriteLine("我是无限循环");}

常见题目:百钱百鸡,兔子生小兔子(斐波拉且数列),猜价格(价格截半法)

        static void Main(string[] args){//某人有100元钱,要买100只鸡。//公鸡5元钱一只,母鸡3元钱一只,小鸡一元钱3只。//编程计算可买到公鸡,母鸡,小鸡各为多少只?//首先从循环次数上将,从公鸡开始循环次数最少//首先100元最多买20只公鸡,for (int i = 0; i < 20; i++)//i为公鸡数 {//j为母鸡数for (int j = 0; j < 33; j++){if ((100-i-j)%3==0&&i*5+j*3+(100-i-j)/3==100){Console.WriteLine($"公鸡={i},母鸡={j},小鸡={100-i-j}");}}}          Console.ReadLine();}
     static void Main(string[] args){//程序循环猜商品价格//首先定义价格范围int max = 1000;int min = 1;//定义随机数Random rnd = new Random();//定义一个标记,一会使用goto重新从标记位执行代码,方便测试使用Flag://随机一个正确价格int correctPrice = rnd.Next(min,max+1);Console.WriteLine($"正确价格是:{correctPrice}");//开始猜价格for (int i = 1;; i++){int price = (min + max) / 2;if (correctPrice > price){Console.WriteLine($"第{i}次猜测的价格:{price},低了");min = price + 1;}else if (correctPrice < price){Console.WriteLine($"第{i}次猜测的价格:{price},高了");max = price - 1;}else{Console.WriteLine($"恭喜你,第{i}次猜测的价格:{price},正确");break;}}if (Console.ReadKey().KeyChar=='A'){min = 1;max = 1000;goto Flag;}Console.ReadLine();}

注意:理解案例中的for循环的运用以及价格截半的精髓(二分查找),另外案例中有个goto关键字的运行和使用

  • foreach

使用foreach可以迭代数组或者一个集合对象。

        static void Main(string[] args){string[] arrStr = new string[] { "ab", "cd", "ef" };foreach (var item in arrStr){Console.WriteLine($"遍历数组-当前项{item}");}Console.ReadLine();}

foreach 迭代遍历只能是正向的,不可逆的,逐个的遍历数组中的每一个元素;迭代遍历时,被迭代的数组的元素不能更改;迭代遍历的速度远快于for循环。

  • while 和do…while

简单使用案例:

         static void Main(string[] args){/* 局部变量定义 */int a = 10;/* while 循环执行 */while (a < 20)//只要条件为true,也可无限循环下去{Console.WriteLine("a 的值: {0}", a);a++;}Console.ReadLine();}
     static void Main(string[] args){/* 局部变量定义 */int a = 10;/* do 循环执行 */do{Console.WriteLine("a 的值: {0}", a);a++;} while (a < 20);Console.ReadLine();}

先执行do,然后判断while的条件,当条件为true的时候才进入循环;相较于while循环,do…while无论是否满足循环条件,都会先执行一次业务代码。

  • 循环控制语句

循环控制语句更改执行的正常序列。当执行离开一个范围时,所有在该范围中创建的自动对象都会被销毁

控制语句 描述
break 终止 loop 或 switch 语句,程序流将继续执行紧接着 loop 或 switch 的下一条语句。
简单说:在loop中使用break将跳出整个循环
continue 跳出本轮循环,开始下一轮循环

10. 数组&字符串&结构体&枚举

1、数组
数组是一个存储相同类型元素的固定大小的顺序集合。数组是用来存储数据的集合,通常认为数组是一个同一类型变量的集合。
数组中重要的三个组成部分就是:元素(数组中的每一项都是一个元素),长度(数组的长度),索引(从0开始)

使用案例:

         //声明数组int[] nums;//初始化数组double[] scores=new double[10];//赋值给数组--逐个元素赋值double[] doubles=new double[10];doubles[0] = 10.1;doubles[1] = 10.2;//初始化并赋值给数组,可省略数组长度double[] doubles1 = new double[]{10.1,10.2 };//简化赋值过程double[] doubles2 = { 10.1, 10.2, 10.3 };//访问数据元素,通过索引double num = doubles2[0];//不过大多时候,都是使用for 和foreach 来操作数据for (int i = 0; i < doubles2.Length; i++){Console.WriteLine($"元素doules[{i}]={doubles2[i]}");}Console.ReadLine();

数组扩展内容见:C#数组详解

2、字符串
在 C# 中,您可以使用字符数组来表示字符串,但是,更常见的做法是使用 string 关键字来声明一个字符串变量。string 关键字是 System.String 类的别名。
关于字符串的详细内容可见:C#字符串使用详解

3、结构体
在 C# 中,结构体是值类型数据结构。它使得一个单一变量可以存储各种数据类型的相关数据。struct 关键字用于创建结构体。

结构体特点如下:

  • 结构可带有方法、字段、索引、属性、运算符方法和事件。
  • 结构可定义构造函数,但不能定义析构函数。但是,您不能为结构定义无参构造函数。无参构造函数(默认)是自动定义的,且不能被改变。
  • 与类不同,结构不能继承其他的结构或类。
  • 结构不能作为其他结构或类的基础结构。
  • 结构可实现一个或多个接口。
  • 结构成员不能指定为 abstract、virtual 或 protected。
  • 当您使用 New 操作符创建一个结构对象时,会调用适当的构造函数来创建结构。与类不同,结构可以不使用 New 操作符即可被实例化。
  • 如果不使用 New 操作符,只有在所有的字段都被初始化之后,字段才被赋值,对象才被使用。

另外结构体与类的区别

  • 类是引用类型,结构是值类型。
  • 结构不支持继承。
  • 结构不能声明默认的构造函数。
  • 结构体中声明的字段无法赋予初值,类可以:
  • 结构体的构造函数中,必须为结构体所有字段赋值,类的构造函数无此限制:

代码如下:

using System;
using System.Text;struct Books
{private string title;//结构体中声明的字段无法赋予初值,类可以:private string author;private string subject;private int book_id;public void setValues(string t, string a, string s, int id){title = t;author = a;subject = s;book_id =id;}public void display(){Console.WriteLine("Title : {0}", title);Console.WriteLine("Author : {0}", author);Console.WriteLine("Subject : {0}", subject);Console.WriteLine("Book_id :{0}", book_id);}};  public class testStructure
{public static void Main(string[] args){Books Book1 = new Books(); /* 声明 Book1,类型为 Books */Books Book2 = new Books(); /* 声明 Book2,类型为 Books *//* book 1 详述 */Book1.setValues("C Programming","Nuha Ali", "C Programming Tutorial",6495407);/* book 2 详述 */Book2.setValues("Telecom Billing","Zara Ali", "Telecom Billing Tutorial", 6495700);/* 打印 Book1 信息 */Book1.display();/* 打印 Book2 信息 */Book2.display();Console.ReadKey();}
}

4、枚举
枚举是一组命名整型常量。枚举类型是使用 enum 关键字声明的。
C# 枚举是值类型。换句话说,枚举包含自己的值,且不能继承或传递继承。

  • 枚举是值类型的数据,只能定义值类型的内容,枚举是将值进行包装
  • enum 默认自带public static ,无需实例化
  • enum和int的值是相互参照的,enum中的值与int转换的时候,默认按照0,1,2的顺序排序,也可以自行定义enum中每一项枚举的值

使用案例如下:

    //声明enum变量,不定义各项的值,默认enum Days { Sun, Mon, Tue, Wed, Thu, Fri, Sat };//声明enum变量,自定义各项的值enum Day{Sun = 10,Mon = 20, Tue = 30, Wed = 40, Thu = 50, Fri = 60, Sat = 70,}//混合情况,第 n 个符号值与第 n-1 个有关,如:此时Mon为  11enum WeekDay{Sun = 10, Mon, Tue, Wed = 40, Thu, Fri, Sat,}class Program{static void Main(string[] args){//默认情况下,枚举中的值与int相互转换,从0开始依次增加int x = (int)Days.Sun;int y = (int)Days.Fri;Console.WriteLine("Sun = {0}", x);//Sun = 0Console.WriteLine("Fri = {0}", y);//Sun = 5Day day = (Day)20;//将int值转化为枚举Console.WriteLine(day.ToString());//将枚举转换成字符串,结果:Mon//将字符串转化为枚举Day day1 = (Day)Enum.Parse(typeof(Day), "Mon");//如果Mon在不在枚举内,这种情况下会报错//混合情况,第 n 个符号值与第 n-1 个有关。int dy = (int)WeekDay.Mon;int dx= (int)WeekDay.Tue;int dz= (int)WeekDay.Sat;Console.WriteLine("WeekDay\tMon = {0}", dy);//WeekDay Mon = 11Console.WriteLine("WeekDay\tTue = {0}", dx);//WeekDay Tue = 12Console.WriteLine("WeekDay\tSat = {0}", dz);//WeekDay Sat = 43Console.ReadLine();}}

关于枚举的进阶用法,详情可见:C#枚举进阶用法

11. C#关键字之修饰符

C#中的修饰符都是关键字

1、访问修饰符

C# 封装根据具体的需要,设置使用者的访问权限,并通过 访问修饰符 来实现。
一个 访问修饰符 定义了一个类成员的范围和可见性。

  • protected internal 是 protected 和 internal 的并集,满足任何一个即可
  • 可访问性排序:public > internal > protected > private

2、其他修饰符

常用修饰符还有:

static、abstract、virtual、override、sealed、readonly、extern、event、const、async、in、new、out

不常用的修饰符有:unsafe、volatile

这里会对部分修饰符的使用进行整理汇总,其余部分如果在后续深入的过程中涉及到也会逐步整理出来

  • static 静态的
    • 使用 static 修饰符可声明属于类型本身而不是属于特定对象的静态成员。 static 修饰符可用于声明 static 类。 在类、接口和结构中,可以将 static 修饰符添加到字段、方法、属性、运算符、事件和构造函数。 static 修饰符不能用于索引器或终结器。
    • 如果 static 关键字应用于类,则类的所有成员都必须为 static。
    • 程序默认就创建实例,因此static对象无需实例化,直接使用;
    • 类中静态变量,它只是定义在当前类中,但是本身不属于类,它早已经实例化,因此调用的时候直接使用类名 + 点(.)运算符进行调用
    • 使用过多的静态对象,会比较消耗内存,因为它默认就实例化了,已经占好了内存

使用案例如下:

    class UserInfo{private string _id;//静态变量public static string Info;//普通变量public string Id{get { return _id; }set { _id = value; }}}class Program{static void Main(string[] args){//使用静态变量,无需实例化,直接通过类名.string info = UserInfo.Info;//使用普通变量,需要先实例化才可以string id = new UserInfo().Id;Console.ReadLine();}}
  • abstract 抽象的
    abstract 修饰符可用于类、方法、属性、索引和事件

抽象方法

    • 抽象方法是隐式的虚拟方法,abstract方法默认自带virtual属性
    • 只有抽象类中才允许抽象方法声明。
    • 由于抽象方法声明不提供实际的实现,因此没有方法主体;方法声明仅以分号结尾,且签名后没有大括号 ({ })。
    • 在抽象方法声明中使用 static 或 virtual 修饰符是错误的。

抽象方法如下:

public abstract void  GetInfo();//实现由方法 override 提供,它是非抽象类的成员。

抽象类

    • 抽象类不能实例化。
    • 必须有子类继承
    • 派生自抽象类的非抽象类,必须包含全部已继承的抽象方法和访问器的实际实现。
      (简单说:子类必须实现抽象父类的所有抽象方法)
    • 在抽象方法声明中使用 static 或 virtual 修饰符是错误的。
  • sealed 封闭的
    通常用于实现第三方类库时不想被客户端继承,或用于没有必要再继承的类以防止滥用继承造成层次结构体系混乱。恰当的使用sealed修饰符也可以在一定程度上提高运行效率,因为不用考虑继承类会重写该成员。

sealed的作用

    • 在类声明中使用sealed可防止其它类继承此类;
    • 在方法声明中使用sealed修饰符可防止子类重写此方法。
    • sealed修饰符主要用于防止非有意的派生,但是它还能促使某些运行时优化
    • 密封类中永远不可能有任何派生类。如果密封类实例中存在虚拟成员函数,该成员函数可以转化为非虚的,函数修饰符virtual 不再生效。


11. 方法

首先在C#中对于函数和方法并没有明确的定义区分,本质上是一样的,只是叫法不同;某些情况下,如我们会更习惯叫构造函数,而不叫构造方法。

熟悉方法无非两点:定义方法和调用方法。
定义方法:

<Access Specifier> <Return Type> <Method Name>(Parameter List)
{Method Body
}访问修饰符 方法修饰符 返回类型 函数名( 参数列表 )
{函数体;
}//实例如下:
public void GetInfo(string id)
{//....
}

调用方法:
调用:通过方法名调用方法,如

Rectangle rectangle = new Rectangle();
//Display即是矩形对象中的方法,通过方法名调用即可
rectangle.Display();

12. 类

1、类的基本内容

  • 当你定义一个类时,你定义了一个数据类型的蓝图。
  • 构成类的方法和变量称为类的成员。
  • 访问标识符 指定了对类及其成员的访问规则。如果没有指定,则使用默认的访问标识符。类的默认访问标识符是 internal,成员的默认访问标识符是 private。
  • 如果要访问类的成员,你要使用点(.)运算符。点运算符链接了对象的名称和成员的名称。

2、构造函数

  • 类的 构造函数 是类的一个特殊的成员函数,当创建类的新对象时执行。
  • 构造函数提供了一种对象的多种创建方式。
  • 构造函数的名称与类的名称完全相同,它没有任何返回类型。

认识一下构造函数,代码如下:

    class Student{public string Name { get; set; }public double Score { get; set; }//构造函数,没有任何返回类型public Student(){}}

构造函数分为:默认/隐式构造函数 和参数化构造函数

  • 默认构造函数,没有参数列表,没有代码,默认隐藏不显示,有且仅有一个
  • 参数化构造函数,手工定义,只要参数列表不同,可以有N个
  • 如果类中定义了一个参数化的构造函数,默认会把隐式的构造函数替换掉
  • 如果需要支持或者用到 无参数的构造函数,就需要定义起来
    class Student{public string Name { get; set; }public double Score { get; set; }//默认构造函数,没有任何返回类型public Student(){}//参数化构造函数public Student(string name){}//参数化构造函数public Student(string name, double score){}}

3、析构函数(终结器)

终结器(以前称为析构函数)用于在垃圾回收器收集类实例时执行任何必要的最终清理操作。 在大多数情况下,通过使用 System.Runtime.InteropServices.SafeHandle 或派生类包装任何非托管句柄,可以免去编写终结器的过程。

  • 无法在结构中定义终结器。 它们仅用于类。
  • 一个类只能有一个终结器。
  • 不能继承或重载终结器。
  • 不能手动调用终结器。 可以自动调用它们。
  • 终结器不使用修饰符或参数。
class Car
{~Car()  // finalizer{// cleanup statements...}
}public class Destroyer
{public override string ToString() => GetType().Name;~Destroyer() => Console.WriteLine($"The {ToString()} finalizer is executing.");
}

不应使用空终结器。 如果类包含终结器,会在 Finalize 队列中创建一个条目。 此队列由垃圾回收器处理。 当 GC 处理队列时,它会调用每个终结器。 不必要的终结器(包括空的终结器、仅调用基类终结器的终结器,或者仅调用条件性发出的方法的终结器)会导致不必要的性能损失。

程序员无法控制何时调用终结器,因为这由垃圾回收器决定。 垃圾回收器检查应用程序不再使用的对象。 如果它认为某个对象符合终止条件,则调用终结器(如果有),并回收用来存储此对象的内存。 可以通过调用 Collect 强制进行垃圾回收,但多数情况下应避免此调用,因为它可能会造成性能问题。

4、内部类

顾名思义就是类中定义的类。
内部类的目的 是为了隐藏一个类中的类 ,保护内部的类

13. 接口

接口本身并不实现任何功能,它只是和声明实现该接口的对象订立一个必须实现哪些行为的契约。接口更像是抽象方法的一个集合

    interface IDataLink{void Contect();void DisContect();}
  • 1 抽象类是类,可以定义变量,有构造函数,使用abstract 是禁止实例
  • 2 接口不是类,里面可以定义变量,但是必须赋值,因为他只是抽象方法集合,所以必须自己赋初始值 实例化
  • 3 接口中方法默认都是public abstract

14. 接口和抽象类

相同点:

  • 1、 都不能实例化
  • 2、 实现类 都必须实现所有抽象方法

不同点:

  • 1 接口是多重继承,抽象类是单一继承
  • 2 一个类只能继承一个父类,但是可以实现n个接口
  • 3 抽象类是类,接口不是类(抽象方法的集合)

其余涉及到面向对象编程的内容,如:封装,继承,多态等将在下一篇博客中进行展开~


结语

以上就是本文的内容,希望以上内容可以帮助到您,如文中有不对之处,还请批评指正。


参考资料:
C# 语言介绍
C#教程
装箱与拆箱

C#基础之基础语法(一)相关推荐

  1. python点操作符语法_最基础的python语法

    最基础的pyth语法 1 python严格区分大小写 2 Python中的每一行就是一条语句,每条语句以换行结束 print(1233) print('eeeee') 3 多行编写时语句后边以\结尾 ...

  2. C++ 基础概念、语法和易错点整理

    目录 基础知识 构造函数与析构函数 虚函数 继承 单例模式 重载.隐藏和重写(覆盖) vector 扩容机制应注意的问题 STL 迭代器 前言 快秋招了,专门用一篇博客整理一下 C++ 的一些基础概念 ...

  3. Python零基础入门(一)——Python基础关键字和语法[学习笔记]

    Python零基础入门(一)--Python基础关键字和语法 目录 1. Hello World! 2. 字符串操作 3. 简单数学计算 4. if elif else 5. 循环 基础类型 pyth ...

  4. 【ROS基础】ROS_c++ 语法记录

    系列文章目录 [ROS基础]Linux 命令行 [ROS基础].launch 文件语法记录 [ROS基础]CMakeLists.txt 文件语法记录 [ROS基础]Package.xml 文件语法记录 ...

  5. CSS基础(emmet 语法,CSS 复合选择器, 布局认知,背景样式)

    CSS基础 1. emmet 语法 -- 开发效率 1.1 emmet 语法生成 html 标签 emmet 的特点和作用是什么? 通过简写提高编码效率. emmet 生成 HTML 结构语法 序号 ...

  6. JAVA基础之java语法

    JAVA基础之java语法 第一个java程序 // HelloWorld类名和文件名相同 public class HelloWorld {// 公开的 static 静态的 void 没有返回值 ...

  7. Golang 基础之基础语法梳理 (一)

    大家好,今天将梳理出的 Go语言基础语法内容,分享给大家. 请多多指教,谢谢. 本次<Go语言基础语法内容>共分为三个章节,本文为第一章节 Golang 基础之基础语法梳理 (一) Gol ...

  8. 1 Java基础后端-基础语法

    1 Java基础后端-基础语法 编程语言介绍 java介绍 文章目录 1 Java基础后端-基础语法 1.1. 计算机语音发展 1.2. Java和C比较 1.3. windows常用DOS 1.4. ...

  9. java玩转区块链-基础篇-solidity语法-基础类型

    java玩转区块链-基础篇-solidity语法-基础类型 java环境配置 代码准备 maven 完整solidity 执行步骤 基础类型 布尔类型 类型标识: 字面常量值: 运算符: 短路规则: ...

  10. 第二课 基础篇_SQL语法

    第二课 基础篇_SQL语法 一.通用语法 1.SQL语句可以单行或多行书写,分号结尾. 2.SQL语句可以使用空格或缩进增强语句的可读性. 3.MySQL数据库库的SQL语句不区分大小写,关键字建议使 ...

最新文章

  1. C实现socket编程
  2. Winform中设置BackgroundWorker在取消时关闭后台进程
  3. hihoCoder 1052 基因工程 最详细的解题报告
  4. 开滦二中2021高考成绩查询,2021唐山中考录取分数线查询
  5. 一个关于 客户端非法取消正在进行的数据提交操作 的问题 的讨论
  6. java汉字的编码_Java中文编码问题小结
  7. 百度富文本编辑器的宽度自适应
  8. 转型只争朝夕!又一火电企业成立新能源公司
  9. 牛市真的来了吗?牛市还能留多久?
  10. 在线APP设计平台,APP在线开发工具有哪些?
  11. 西安交大软件学院推免远程面试夏令营分享
  12. 小程序 - 接入支付宝预授权支付 笔记
  13. Android 常用API自查表(二)
  14. java计算机毕业设计家庭园艺服务平台源码+数据库+lw文档+系统
  15. java字符串tirm方法模拟去除首尾空白字符
  16. PyDraw 所见即所得的 Python GUI 绘制框架 开源代码源自 JY Lin
  17. 【题库】上海学校心理咨询-普通心理学-考点解析 4.4 知觉的特征
  18. 【JAVA】MANIFEST.MF / CERT.SF 中 文件SHA1-Digest计算方法
  19. python经典类新式类_菜鸟世界 -python进阶---新式类与经典类
  20. 用户数据权利请求响应具体都包括哪些内容

热门文章

  1. 【CSS】CSS 规避脱标之两种用法
  2. 缓和曲线04四次两段曲线
  3. 这么多年不容易...我很庆幸等到现在的你——知乎上关于男人成熟的好故事
  4. Cesium功能实现(一)创建billboard广告牌
  5. Numerical solution of Bloch‘s equation for neutron spin precession
  6. C语言用递归法实现十进制转二进制
  7. 毕业论文常见数据格式汇总
  8. pmp知识点整理和答题技巧
  9. 通过android设备自身的init.qcom.post_boot.sh实现修改zram大小
  10. 干货分享!悬浮按钮设计规范和经典实践