C Sharp(C#) 学习笔记

236 阅读16分钟

C sharp (C#)

1 C#准备知识

1.1 启动 VS 命令

devenv - (development envirnment)

1.2 .Net Framework 编写应用程序的过程

程序代码 => CIL(存放在程序集合中)=>(JIT编译器)本机代码 native code => CLR托管 EXE DLL

1.3 第一个控制台程序

namespace _1第一个控制台程序
{
    class Program
    {
        static void Main(string[] args) {
            Console.WriteLine("Hello World!!!");
            Console.ReadKey(); // 等待用户输入,常用来对程序界面进行停留。
        }
    }
}

注:Console.WriteLine() 可以用 {索引号} 占位符输出变量,如:

Console.WriteLine("您好:{0}您的年龄是{1}是个{2}生", name, age, sex);

1.4 C#中三种注释符

  1. 单行注释——//注释内容
  2. 多行注释——/*注释内容*/
  3. 文档注释(在方法或类的上一行输入)——/// 注释内容 ///

1.5 VS常用快捷键

Ctrl+Shift+N:新建项目;

Ctrl+K+D: 快速对齐代码(格式化代码);

Ctrl+Z:撤销;

Ctrl+S:保存;

Ctrl+J:快速弹出智能提示;

Shift+End:快速选中光标到行尾的内容;

Shift+Home:快速选中光标到行首的内容;

Ctrl+K+C:注释所选代码;

Ctrl+K+U:取消对所选代码的注释;

F1:转到帮助文档;

1.6 第一个桌面程序

新建 WPF Application(或WindowsForm)

// MainWindow.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
​
namespace HelloWorldWPF
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
​
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Hello World!!!", "第一个 WPF 程序");
        }
    }
}
// MainWindow.xaml 样式文件
<Window x:Class="HelloWorldWPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:HelloWorldWPF"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Button Width="100" Height="50" Background="#FF0056FF" Foreground="White" FontSize="16" FontWeight="Bold" BorderThickness="0,0,0,0" Click="Button_Click">测试</Button>
    </Grid>
</Window>

1.7 程序结构

using System; // 引用命名空间namespace _1第一个控制台程序 // 命名空间或项目名称
{
    class Program // Program 类
    {
        static void Main(string[] args) // static-静态,void-无返回值,Main 函数也是我们程序的起点
        {
            Console.WriteLine("Hello World!!!");
        }
    }
}

2 C# 基础语法

2.1 C# 程序结构

.Sln:解决方案文件;

.csproj:项目文件;

.cs:类文件;

解决方案文件和项目文件以及类文件之间的关系:解决方案文件包含项目文件,项目文件包含类文件。

解决方案下可包含多个项目,在解决方案上右键选择属性,可以设置默认运行的项目。

2.2 命名空间及标识符、关键字

2.2.1 命名空间

命名空间(namespace)是 .NET 中提供应用程序代码容器的方式,用来唯一地表示代码及其内容。 创建命名空间的关键字是 namespace。 命名空间是以“层”形式存在的,如有多层,则以“.”分开。 如果命名空间名称太长,可以给命名空间一个别名,语法为:using 别名=命名空间,用法如下:

using CW = System.Console;
​
namespace _1第一个控制台程序
{
    class Program
    {
        static void Main(string[] args)
        {
            CW.WriteLine("Hello World!!!");
        }
    }
}

2.2.2 标识符

标识符是编程人员为变量、常量、数据类型、方法、函数、属性、类、程序等定义的名称。

例如:string username 中的 username 为标识符。

注意:

  1. 标识符只能由大写字母,小写字母,数字和下划线组成;
  2. 标识符必须以字符或者下划线开头;
  3. C 语言是区分大小写的, usernameUsername 是不同的标识符;
  4. 如果在 C# 中需要将关键字作为标识符就要在前面加上 @

2.2.3 关键字

对于 C# 编译器而言,具有特定含义的名称,比如程序中的 using,class,static,void等,关键字不可用作标识符。

3 变量、常量与数据类型

3.1 变量

声明变量:数据类型 变量名;

一次性声明多个相同类型的变量可用逗号隔开:string zsName,IsName;

变量一定要先声明,再赋值,才能使用。

变量的命名规则:

  1. 必须以字母、下划线或@符号开头,不能以数字开头;

  2. 后面可以跟任意字母、数字或下划线。

  3. 注意:

    1. 不能与 C# 中的关键字重复;
    2. 在 C# 中,大小写是敏感的;
    3. 同一个变量名不可重复定义;
    4. 定义变量时,变量名要有意义;
    5. 英文字母缩写全用大写;

3.2 常量

常量是指在程序运行时不能改变的数据。

声明常量:const 数据类型 常量名称 = 常量值;

注意:一定要给常量赋值,赋值后不给改变。

3.3 变量、常量作用域

一般确定作用域有以下规则:

  • 局部变量存在于声明该变量的块语句或方法的大括号内。
  • forwhileforeach等循环语句中声明的变量,只存在于该循环体内。

总之,变量作用域为包含它的大括号。

3.3 @作用

  1. 忽略转义字符

    // 不使用 @
    string fileName = "D:\51zxw\text.txt";
    // 使用 @
    string fileName = @"D:\51zxw\text.txt";
    
  2. 让字符串跨行(代替 +)

    // 不使用 @ 
    string SQLStr = "SELECT * FROM HumanResources.Employee AS e"
                    + " INNER.JOIN Person.Contact AS c"
                    + " ON e.ContactID = c.ContactID"
                    + " ORDER BY c.LastName";
    // 使用 @
    string SQLStr = @"SELECT * FROM HumanResources.Employee AS e
    INNER.JOIN Person.Contact AS c
    ON e.ContactID = c.ContactID
    ORDER BY c.LastName";
    
  3. 在标识符中的用法

    C# 不允许使用关键字作为标识符(类名、变量名、方法名、表空间名等)使用,但如果加上@之后就可以了,例如:@namespace@class

3.4 数据类型

数据类型是表示具有多种相同特征的一组数据。

C# 预定义的数据类型包括值类型和引用类型。

3.4.1 值类型

值类型是在栈中操作。

值类型直接保存其值,如 int (整型)就属于值类型,如声明了一个整型变量,并给它赋予另一个整型变量的值,则在内存事先复制一个整型变量的值,然后将其赋予刚声明的整型变量,这时内存中就会有两个整型值。

值类型包括数值类型、布尔类型、字符类型等。

  • 整数类型

    数据类型说明取值范围对应于System程序集中的结构
    sbyte有符号3位整数-128 ~ 127SByte
    byte无符号8位整数0 ~ 255Byte
    short有符号16位整数-32768 ~ 32767Int16
    ushort无符号16位整数0 ~ 65534UInit16
    Int有符号32位整数-2147489648 ~ 2147483647Int32
    uint无符号32位整数0 ~ 42994967295UInit32
    long有符号64位整数-2^63 ~ 2^63Int64
    ulong无符号64位整数0 ~ 2^64UInt64
  • 浮点类型

    数据类型说明取值范围
    float32位单精度实数1.510^(-45) ~ 3.410^38
    double64位双精度实数5.010^(-324) ~ 1.710^(308)
    demcimal128位十进制实数1.010^(-28) ~ 7.910^28
  • 布尔类型

    只用 true、false 两个值,关键字为 bool,在计算机中占4个字节(4B),即32位存储空间,但不能用0和1代替。

  • 字符类型

    即保存单个字符的值,字符类型的关键字是char,每个字符对象与Unicode字符集的字符对应,char类型的字符变量是用单引号括起来的,如果把字符放在双引号中,编译器会将其认为字符串。

3.4.2 引用类型

引用类型在堆中分配存储单元。

引用类型的变量在内存中是直接保存其值的引用。C# 中大多数复杂数据类型都是引用类型,例如类就是引用类型。

在 C# 预定义的类型中,属于引用类型的有对象(object)类型和字符串(string)类型两种。

  • object 类型:是所有其他类型的基类型,所以可把任何类型的值赋给它。

  • String 类型:在 C# 中,字符串(string)类型是用一对双引号引起来的字符。注意:

    1. 字符串的不可变形:当个一个字符串重新赋值后,老值并没有销毁,而是重新开辟一块空间存储新值,当程序结束后,GC 扫描整个内存,如果发现有的空间没有被指向,则立即把它销毁。
    2. 字符串可以看做是 char 类型的一个只读数组。

3.4.3 值类型与引用类型的区别

  1. 值类型和引用类型在内存上存储的地方不一样。
  2. 在传递值类型和传递引用类型的时候,传递的方式不一样。

值类型我们称之为值传递,引用类型我们称之为引用传递。

3.4.4 类型转换

  • 使用 Convert ,如将字符串类型转为 int 类型:
int time = Convert.ToInt32(Console.ReadLine());
  • int.Parse(字符串)

4 运算符

4.1 布尔运算符

运算符类别示例表达式结果
&&二元var3 = var1 && var2同时为 true 时结果为 true
二元var3 = var1var2一个为 true 时结果为 true
!一元var3 = !var1var1 为 true 时结果为 false
二元var3 = var1 ^ var2有且只有一个为 true 时结果为 true
&二元var3 = var1 & var2同时为 true 结果为 true
二元var3 = var1var2一个为 true 时结果为 true

4.2 位运算符

位(bit):在计算机中存储所有数据都采用二进制。

  • 1Byte = 8bit(1字节 = 8位)
  • 1K = 1024Byte
  • 1M = 1024K
  • 1G = 1024M
  • 1T = 1024G
运算符类别示例表达式结果
~ (按位取反)一元//
& (与)二元//
(或)二元//
^ (亦或)二元//
<< (左移)二元var3 = var1 << var2var1 向左移动 var2 位,将所得值赋值给 var3
>> (右移)二元var3 = var1 >> var2var1 向右移动 var2 位,将所得值赋给 var3

注意:

  • 大多数代码中都不使用这些运算符,主要用于高度优化的代码,常用于驱动程序或系统代码。
  • << 一位,相当于乘以 2
  • 一位,相当于除以 2,然后去除非整数部分

4.3 其他运算符

  • 字符串连接运算符 + :将两个字符串连接在一起组成一个新的字符串,如

    string str1 = "my name is";
    string str2 = " snowskywalker";
    string str3 = str1 + str2; // str3 = "my name is snowskywalker";
    
  • is 运算符:用于动态检查对象的运行时类型是否与给定类型兼容。如

    string str = "my name is";
    bool b = str is string;
    Console.WriteLine(b); // 输出 True
    

4.4 运算符的优先级

优先级类别运算符
1基本(x) .y .(x) [x] ++ x-- new typeof sizeof checked unchecked
2单目+ - ! ~ ++x --x (T)x
3乘法与除法* / %
4加法与减法+ -
5移位运算<< >>
6关系运算< <= > >= is
7条件等== !=
8位逻辑与&
9位逻辑异或
10位逻辑或
11条件与&&
12条件或
13条件?:
14赋值= += -= *= /= <<= >>= ^==

优先级数越小,优先级别也就越高;

当操作相同优先级的两个运算符时,运算符的执行顺序遵循如下原则:

1. 除了复制运算符外,所有的二元运算符执行顺序都是“从左向右”;
2. 赋值运算符和条件运算符(三元运算符)都是按照“从左向右”的顺序执行;

当执行多个运算符时,在运算符的优先级不确定时,为了提高程序的可读性和清晰度,可使用括号进行顺序控制。

5 流程控制

5.1 分支语句

分支语句是指根据实际情况决定逻辑路径的代码。

  • if

    if(判断条件表达式)
    {
        // 表达式为 true 时执行
    }
    else
    {
        // 表达式为 false 时执行
    }
    
  • switch

    switch(表达式)
    {
        case 常量表达式: 条件语句;
        case 常量表达式: 条件语句;  
        case 常量表达式: 条件语句;
        default: 条件语句;
    }
    
  • ? :

    条件判断表达式 ? 成立时执行的语句 : 不成立时的语句;
    

总结:

  • if 语句适合判断一些连续的值;
  • switch 语句适合判断一些离散的值,每个 case 语句之后都必须有 break 语句;
  • 三元运算符适合简单的赋值语句,可读性较差;

5.2 迭代语句

迭代语句是指在程序中重复执行,直到满足指定条件才停止的一段代码。

  • while

    while(条件表达式)
    {
        // 循环体语句
    }
    
  • do...while

    循环体语句至少执行一次,即使 while 条件语句不成立。

    do
    {
        // 循环体语句
    }while(判断语句)
    
  • for

    for(初始条件;判断条件;循环条件)
    {
        // 循环体语句
    }
    

    注意:初始条件,判断条件和循环条件都能省略,但是分号不能省略。

  • foreach

    foreach(类型 变量 in 集合)
    {
        // 代码体
    }
    

    补充:string 类型可以看成是 char 类型的一个集合。

5.3 跳转语句

跳转语句是程序运行到某个位置时,可以调到程序中另一行代码的语句。

  • break

    break 语句的作用:

    1. 在 switch 语句中用于从 case 语句中跳出,结束 switch 分支语句;
    2. 用于跳出迭代语句,结束当前循环。
  • continue

    意义:用于停止当前的迭代语句,结束本次循环,break 是直接结束循环。

    使用:

    continue;
    
  • return

    return 语句使用时一般有两种格式:

    1. return;
      
    2. return 表达式;
      

    说明:return 语句只能出现在方法当中,当调用方法时,执行到 return 语句时,直接跳转到 Main() 函数。

  • goto

    goto 标识符;
    

    标识符标识程序位置的方法,当程序执行到 goto 语句时,程序会直接跳转到标识符所标识的程序位置,并继续执行代码。

    goto 语句会使代码的易读性下降,在编写程序时尽量少用 goto 语句。

6 字符与字符串

6.1 字符及转义字符

6.1.1 字符

char 类结构表示 unicode 字符。

Unicode 标准使用称为码位的唯一的21位标量数字标识每个 Unicode 字符,并定义 UTF-16 编码格式,这一格式指定如何将码位编码为一个或多个16位值的序列,每个16位值的范围为十六进制的 0x0000 ~ 0xFFFF,并存储在 Char 结构中。Char 对象的值是其16位数字(序号)值。

定义格式:

char 变量名 = '初始值';

char 类常用方法:

方法作用
IsLetter是否是字母
IsDigit是否是数字
IsLetterOrDigit是否是数字或字母
IsLower是否是小写
IsUpper是否是大写
IsPunctuation是否是标点
IsSeparator分隔符
IsWhiteSpace是否是空格
ToLower转化为小写
ToUpper转化为大写

例如:

char.IsLetter('&'); // False

6.1.2 转义字符

转义符作用
'单引号
"双引号
\反斜杠
\0空字符
\aalert 感叹号
\b退格
\f换页
\n新行
\r回车
\t水平 tab
\v竖直 tab

6.2 字符串

字符串是由零个或多个字符组成的有限序列,是 System.String 类的一个引用类型,但与其他引用类型不同的是,C# 将字符串视为一个基本类型,可以声明为一个变量,并为其赋值。

声明方式:

string 变量名 = "初始值";

注意:string 类型变量可以看成是 char 变量的只读数组。

6.2.1 字符集与字符编码

字符集:是一个系统支持的所有抽象字符的集合。

字符编码:是一套法则,使用该法则能够对自然语言的字符的一个集合(如字母表或音节表),与其他东西的一个集合(如号码或电脉冲)进行配对。

常见字符集名称:ASCII字符集、GB2312字符集、BIG5字符集、GB18030字符集、Unicode字符集、UTF-8等。

计算机要准确的处理各种字符集文字,需要进行字符编码,以便计算机能够识别和存储各种文字。

6.2.2 字符串的大小写转换

大写:ToUpper

小写:ToLower

如:

string name = "Jack";
Console.WriteLine(name.ToUpper()) ;
Console.WriteLine(name.ToLower()) ;

6.2.3 字符串的比较

比较方法:

  1. 字符串1 == 字符串2

    例:

    string name1 = "Jack";
    string name2 = "JACK";
    Console.WriteLine(name1 == name2) ;
    
  2. string.Equals(字符串1,字符串2)

    例:

    string name1 = "Jack";
    string name2 = "JACK";
    Console.WriteLine(string.Equals(name1, name2));
    
  3. string.Compare(字符串1,字符串2,布尔值)

    例:

    string name1 = "Jack";
    string name2 = "JACK"; Console.WriteLine(string.Compare(name1,name2,true));
    

    返回一个整数:

    返回值结果
    小于0字符串1 < 字符串2
    等于0字符串1 = 字符串2
    大于0字符串1 > 字符串2

    布尔值为 true 时,忽略大小写进行比较。

  4. 字符串1.CompareTo(字符串2)

    例:

    string name1 = "Jack";
    string name2 = "JACK";
    Console.WriteLine(name1.CompareTo(name2));
    

    返回一个整数:

    返回值结果
    小于0字符串1 < 字符串2
    等于0字符串1 = 字符串2
    大于0字符串1 > 字符串2,或字符串2是null引用

6.2.4 字符串的格式化

string.Format(要转换的格式,格式化的对象);
string.Format(要转换的格式,格式化的对象一,格式化的对象二)

例:

string result = string.Format("{0:C},{1:C}", 20,40);
Console.WriteLine(result); // 输出 ¥20.00,¥40.00

常用数值格式符如下:

方法适用类型含义
C数字类型专用场合的货币值
D只用于整数类型一般整数
E数字类型科学技术法
F数字类型小数点后的位数固定
G数字类型一般整数
N数字类型通用场合数字格式
P数字类型百分数
X只用于整数类型十六进制格式

6.2.5 字符串的截取

  • 字符串1.Substring(整数n)

    将字符串1前n个长度的字符串截取掉,保留后面的字符串。

  • 字符串1.Substring(整数n,整数m)

    保留从字符串1第n个长度开始数m个长度的字符串。

6.2.6 字符串的分割

通过 字符串1.Split(字符或字符数组)分割字符串,返回值为一个字符串数组。

如:

string str = "PHP,是世界上-最好的语言!";
string[] strArr = str.Split(new char[] { ',', '-'});
foreach (string str2 in strArr)
{
    Console.WriteLine(str2+'\n');
}

6.2.7 字符串的合并

  1. +

    字符串3 = 字符串1 + 字符串2

  2. Concat

    string Concat(字符串1,字符串2,字符串3,...,字符串n)

  3. Join

    string.Join(合并后的分隔符,字符串数组);

6.2.8 字符串的插入与填充

  • 插入

    字符串.Insert(插入位置,插入子串)

  • 填充

    str.PadRight(int: totalWidth,char?: paddingChar):string

    str.PadLeft(int: totalWidth,char?: paddingChar):string

    str:源字符串;

    totalWidth:总长度;

    char?:填充的字符,默认为空格;

    通过添加指定的重复字符填充字符串。

例如:

string str = "我要";
Console.WriteLine(str.PadRight(10,'旺')); // 输出 我要旺旺旺旺旺旺旺旺

6.2.9 字符串的删除

删除是通过 Remove 来实现的。

str.Remove(int: startIndex,int?: count)

startIndex:删除的开始字符索引。

count?:从删除的开始字符索引往后数的数量。

从开始位置数到移出数位置的字符删除,移出数可不指定,如果指定,则将开始位置之后所有字符删除。

例如:

string str = "PHP不是世界上最好的语言";
Console.WriteLine(str.Remove(3,1)); // 输出 PHP是世界上最好的语言

6.2.10 字符串修剪

修剪即为删除字符串头尾出现的某些字符,C# 有三个修剪字符串的方法:

  • Trim():删除字符串首部和尾部的空格。
  • TrimStart():删除字符串头部的空格。
  • TrimeEnd():删除字符串尾部的空格。

以上三种方法均可带参数,即为删除指定位置的指定字符。如:

string str = "@wkaals#";
Console.WriteLine(str.Trim("@","#"); // 输出 wkaals
// 等价于
Console.WriteLine(str.Trim("@#".ToCharArray())); // 输出 wkaals

6.2.11 字符串的复制

  • string.Copy(string:str1):string;

    str1:要复制的字符串

    string str1 = "要复制的字符串";
    string str2 = string.Copy(str1);
    Console.WriteLine(str2); // 输出 要复制的字符串
    
  • str.CopyTo(int:sourceIndex,char[]:destination,int:destinationIndex,int:count):void;

    str:要复制的字符串;

    sourceIndex:要复制字符的起始位置;

    destination:目标字符数组;

    destinationIndex:目标数组中的开始存放位置;

    count:要复制的字符个数;

    例如:

    string str1 = "要复制的字符串";
    char[] targetArr = new char[20];
    str1.CopyTo(2, targetArr, 1, 3);
    Console.WriteLine(targetArr); // 输出 制的字