基本语法
usiing 关键字
using 关键字用于在程序中包含命名空间。一个程序可以包含多个 using 语句
class关键字
class 关键字用于声明一个类。
注释
单行注释
多行注释
成员变量
变量是类的属性或数据成员,用于存储数据。
成员函数
也可以叫做成员方法
函数是一系列执行指定任务的语句。类的成员函数是在类内声明的。
类的实例化
只要理解 “类是模板,对象是实例” ,就能掌握实例化的核心思想。
这个过程使用
new
关键字调用类的构造函数来完成。
代码演示:
ClassName instanceName = new ClassName(参数列表);
完整代码演示:
using System;// 1. 定义一个类
public class Person
{// 字段(可选)private string name;private int age;// 属性(推荐使用属性封装字段)public string Name{get { return name; }set { name = value; }}public int Age{get { return age; }set { age = value >= 0 ? value : 0; } // 简单验证}// 无参构造函数public Person(){Name = "未知";Age = 0;}// 有参构造函数public Person(string name, int age){Name = name;Age = age;}// 方法public void Introduce(){Console.WriteLine($"大家好,我叫 {Name},今年 {Age} 岁。");}
}// 2. 主程序:实例化类
class Program
{static void Main(string[] args){// 实例化方式 1:使用无参构造函数Person person1 = new Person();person1.Name = "张三";person1.Age = 25;person1.Introduce(); // 输出:大家好,我叫 张三,今年 25 岁。// 实例化方式 2:使用有参构造函数Person person2 = new Person("李四", 30);person2.Introduce(); // 输出:大家好,我叫 李四,今年 30 岁。// 实例化方式 3:C# 9.0+ 支持 target-typed new 表达式(更简洁)Person person3 = new("王五", 22);person3.Introduce(); // 输出:大家好,我叫 王五,今年 22 岁。// 每个实例都是独立的对象Console.WriteLine($"person1 和 person2 是同一个对象吗?{ReferenceEquals(person1, person2)}"); // False}
}
标识符
标识符是用来识别类、变量、函数或任何其它用户定义的项目
在 C# 中,类的命名必须遵循如下基本规则:
- 标识符必须以字母、下划线或
@ 开头
,后面可以跟一系列的字母、数字( 0 - 9 )、下划线( _ )、@。 - 标识符中的第一个字符不能是数字。
- 标识符必须不包含任何嵌入的空格或符号,比如
? - +! # % \^ & \* ( ) [ ] { } . ; : " ' / \\。
- 标识符不能是 C# 关键字。除非它们有一个 @ 前缀。 例如,@if 是有效的标识符,但 if 不是,因为 if 是关键字。
- 标识符必须区分大小写。大写字母和小写字母被认为是不同的字母。
- 不能与C#的类库名称相同。
CSharp 关键字
关键字是 C# 编译器预定义的保留字。这些关键字不能用作标识符,但是,如果您想使用这些关键字作为标识符,可以在关键字前面加上 @ 字符作为前缀。
作用:
它们是语言的“保留词”,用于定义结构、控制流程、管理内存、实现面向对象和高级功能,不能用作标识符(如变量名)。
在 C# 中,有些关键字在代码的上下文中有特殊的意义,如 get 和 set,这些被称为上下文关键字(contextual keywords)。
顶级语句(Top-Level Statements)
这是C# 9 版本中引入的顶级语句 ,是一种新的编程范式
允许开发者在文件的顶层直接编写语句,而不需要将它们封装在方法或类中。
特点:
- 无需类或方法:顶级语句允许你直接在文件的顶层编写代码,无需定义类或方法。
- 文件作为入口点:包含顶级语句的文件被视为程序的入口点,类似于 C# 之前的
Main
方法。 - 自动
Main
方法:编译器会自动生成一个Main
方法,并将顶级语句作为Main
方法的主体。 - 支持局部函数:尽管不需要定义类,但顶级语句的文件中仍然可以定义局部函数。
- 更好的可读性:对于简单的脚本或工具,顶级语句提供了更好的可读性和简洁性。
- 适用于小型项目:顶级语句非常适合小型项目或脚本,可以快速编写和运行代码。
- 与现有代码兼容:顶级语句可以与现有的 C# 代码库一起使用,不会影响现有代码。
传统代码演示:
using System;namespace MyApp
{class Program{static void Main(string[] args){Console.WriteLine("Hello, World!");}}
}
顶级语句代码演示:
using System;Console.WriteLine("Hello, World!");
顶级语句支持所有常见的 C# 语法,包括声明变量、定义方法、处理异常等。
using System;
using System.Linq;// 顶级语句中的变量声明
int number = 42;
string message = "The answer to life, the universe, and everything is";// 输出变量
Console.WriteLine($"{message} {number}.");// 定义和调用方法
int Add(int a, int b) => a + b;
Console.WriteLine($"Sum of 1 and 2 is {Add(1, 2)}.");// 使用 LINQ
var numbers = new[] { 1, 2, 3, 4, 5 };
var evens = numbers.Where(n => n % 2 == 0).ToArray();
Console.WriteLine("Even numbers: " + string.Join(", ", evens));// 异常处理
try
{int zero = 0;int result = number / zero;
}
catch (DivideByZeroException ex)
{Console.WriteLine("Error: " + ex.Message);
}
注意事项
- 文件限制: 顶级语句只能在一个源文件中使用。如果在一个项目中有多个使用顶级语句的文件,会导致编译错误。
- 程序入口: 如果使用顶级语句,则该文件会隐式地包含 Main 方法,并且该文件将成为程序的入口点。
- 作用域限制: 顶级语句中的代码共享一个全局作用域,这意味着可以在顶级语句中定义的变量和方法可以在整个文件中访问。
简单理解:
顶级语句在简化代码结构、降低学习难度和加快开发速度方面具有显著优势,特别适合于编写简单程序和脚本。
数据类型
在 C#
中,变量分为以下几种类型:
- 值类型(Value types)
- 引用类型(Reference types)
- 指针类型(Pointer types)
值类型
值类型变量可以直接分配给一个值。它们是从类 System.ValueType 中派生的。
值类型直接包含数据。比如 int、char、float,它们分别存储数字、字符、浮点数。当您声明一个 int 类型时,系统分配内存来存储值。
如需得到一个类型或一个变量在特定平台上的准确尺寸,可以使用 sizeof 方法
表达式 sizeof(type) 产生以字节为单位存储对象或类型的存储尺寸。
代码演示:
using System;namespace DataTypeApplication
{class Program{static void Main(string[] args){Console.WriteLine("Size of int: {0}", sizeof(int));Console.ReadLine();}}
}
用来读取多少个字节的
C# 中的值类型直接包含数据,赋值和传参时复制整个值,典型代表包括所有基本类型(int
、bool
等)、struct
和 enum
。
引用类型
引用类型不包含存储在变量中的实际数据,但它们包含对变量的引用。
换句话说,它们指的是一个内存位置。使用多个变量时,引用类型可以指向一个内存位置。
如果内存位置的数据是由一个变量改变的,其他变量会自动反映这种值的变化。
内置的 引用类型有:object、dynamic 和 string。
引用类型就像“快递单”——变量里存的不是东西本身,而是东西的“地址”。多个快递单可以指向同一个包裹,谁改了包裹内容,大家看到的都一样。
对象类型:
当一个值类型转换为对象类型时,则被称为 装箱;另一方面,当一个对象类型转换为值类型时,则被称为 拆箱。
指针类型
但是我目前来说好像并没有怎么去使用过
指针类型变量存储另一种类型的内存地址。C# 中的指针与 C 或 C++ 中的指针有相同的功能。
声明指针类型的语法:
type* identifier;
例如:
char* cptr;
int* iptr;
类型转换
类型转换的概念:在 C# 中,类型转换是将一个数据类型的值转换为另一个数据类型的过程。
C# 中的类型转换可以分为两种:隐式类型转换和显式类型转换(也称为强制类型转换)。
隐士类型转换
隐式转换是不需要编写代码来指定的转换,编译器会自动进行。
像是很平稳的过度 ,小转大
隐式转换是指将一个较小范围的数据类型转换为较大范围的数据类型时,编译器会自动完成类型转换,这些转换是 C# 默认的以安全方式进行的转换, 不会导致数据丢失。
例如,从 int 到 long,从 float 到 double 等。
从小的整数类型转换为大的整数类型,从派生类转换为基类。将一个 byte 类型的变量赋值给 int 类型的变量,编译器会自动将 byte 类型转换为 int 类型,不需要显示转换。
代码演示:
byte b = 10;
int i = b; // 隐式转换,不需要显式转换
将一个整数赋值给一个长整数,或者将一个浮点数赋值给一个双精度浮点数,这种转换不会导致数据丢失:
int intValue = 42;
long longValue = intValue; // 隐式转换,从 int 到 long
显示类型转换
显式类型转换,即 强制类型转换 ,需要程序员在代码中明确指定。
显式转换是指将一个较大范围的数据类型转换为较小范围的数据类型时,或者将一个对象类型转换为另一个对象类型时,需要使用强制类型转换符号进行显示转换,强制转换会造成数据丢失。
例如,将一个 int 类型的变量赋值给 byte 类型的变量,需要显示转换。
int i = 10;
byte b = (byte)i; // 显式转换,需要使用强制类型转换符号
强制转换为整数类型:
但是这样转换的话避免不了的会造成精度丢失的
double doubleValue = 3.14;
int intValue = (int)doubleValue; // 强制从 double 到 int,数据可能损失小数部分
C# 类型转换方法
C# 提供了下列内置的类型转换方法:(我感觉还挺好用的)
序号 | 方法 & 描述 |
---|---|
1 | ToBoolean 如果可能的话,把类型转换为布尔型。 |
2 | ToByte 把类型转换为字节类型。 |
3 | ToChar 如果可能的话,把类型转换为单个 Unicode 字符类型。 |
4 | ToDateTime 把类型(整数或字符串类型)转换为 日期-时间 结构。 |
5 | ToDecimal 把浮点型或整数类型转换为十进制类型。 |
6 | ToDouble 把类型转换为双精度浮点型。 |
7 | ToInt16 把类型转换为 16 位整数类型。 |
8 | ToInt32 把类型转换为 32 位整数类型。 |
9 | ToInt64 把类型转换为 64 位整数类型。 |
10 | ToSbyte 把类型转换为有符号字节类型。 |
11 | ToSingle 把类型转换为小浮点数类型。 |
12 | ToString 把类型转换为字符串类型。 |
13 | ToType 把类型转换为指定类型。 |
14 | ToUInt16 把类型转换为 16 位无符号整数类型。 |
15 | ToUInt32 把类型转换为 32 位无符号整数类型。 |
16 | ToUInt64 把类型转换为 64 位无符号整数类型。 |
这些方法都定义在 System.Convert 类中,使用时需要包含 System 命名空间
它们提供了一种安全的方式来执行类型转换,因为它们可以处理 null值,并且会抛出异常,如果转换不可能进行。这里可以处理null 我觉得就很重要
代码演示:使用 Convert.ToInt32 方法将字符串转换为整数:
这样的使用我其实觉得和Java中的调用各种API是差不多的 ,使用的时候也很方便
string str = "123";
int number = Convert.ToInt32(str); // 转换成功,number为123
不过如果字符串不是有效的整数表示,Convert.ToInt32 将抛出 FormatException。
代码演示:
using System;namespace TypeConversionApplication
{class StringConversion{static void Main(string[] args){// 定义一个整型变量int i = 75;// 定义一个浮点型变量float f = 53.005f;// 定义一个双精度浮点型变量double d = 2345.7652;// 定义一个布尔型变量bool b = true;// 将整型变量转换为字符串并输出Console.WriteLine(i.ToString());// 将浮点型变量转换为字符串并输出Console.WriteLine(f.ToString());// 将双精度浮点型变量转换为字符串并输出Console.WriteLine(d.ToString());// 将布尔型变量转换为字符串并输出Console.WriteLine(b.ToString());// 等待用户按键后关闭控制台窗口Console.ReadKey();}}
}
在进行类型转换时需要注意以下几点:
- 隐式转换只能将 较小范围的数据类型转换为较大范围的数据类型 ,不能 将较大范围的数据类型转换为较小范围的数据类型 ;
- 显式转换可能会导致数据丢失或精度降低,需要进行数据类型的兼容性检查;
- 对于对象类型的转换,需要进行类型转换的兼容性检查和类型转换的安全性检查。
类型转换方法
C# 提供了多种类型转换方法,例如使用 Convert 类、Parse 方法和 TryParse 方法,这些方法可以帮助处理不同的数据类型之间的转换。
这三个在日常使用中 ,我用的还是比较多的 ,也是需要必须掌握的知识
使用 Convert类
Convert 类提供了一组静态方法,可以在各种基本数据类型之间进行转换。
代码演示:
string str = "123";
int num = Convert.ToInt32(str);
使用 Pars方法
作用:Parse 方法用于将字符串转换为对应的数值类型,如果转换失败会抛出异常。
代码演示:
string str = "123.45";
double d = double.Parse(str);
使用 TryParse方法
TryParse 方法类似于 Parse,但它不会抛出异常,而是返回一个布尔值指示转换是否成功。
代码演示:
string str = "123.45";
double d;
bool success = double.TryParse(str, out d);if (success) {Console.WriteLine("转换成功: " + d);
} else {Console.WriteLine("转换失败");
}
自定义类型转换
C# 还允许你定义自定义类型转换操作,通过在类型中定义 implicit 或 explicit 关键字。
不过这个我好像并没有怎么接触过 ,也算是我的一个知识盲区吧
代码演示:
using System;public class Fahrenheit
{public double Degrees { get; set; }public Fahrenheit(double degrees){Degrees = degrees;}// 隐式转换从Fahrenheit到doublepublic static implicit operator double(Fahrenheit f){return f.Degrees;}// 显式转换从double到Fahrenheitpublic static explicit operator Fahrenheit(double d){return new Fahrenheit(d);}
}public class Program
{public static void Main(){Fahrenheit f = new Fahrenheit(98.6);Console.WriteLine("Fahrenheit object: " + f.Degrees + " degrees");double temp = f; // 隐式转换Console.WriteLine("After implicit conversion to double: " + temp + " degrees");Fahrenheit newF = (Fahrenheit)temp; // 显式转换Console.WriteLine("After explicit conversion back to Fahrenheit: " + newF.Degrees + " degrees");}
}
总结:
在 C# 中,内置的类型转换方法主要通过以下几种方式实现:隐式转换、显式转换(强制转换)、使用 Convert 类的方法、Parse 方法和 TryParse 方法,这些方法广泛应用于不同数据类型之间的转换。
变量
一个变量只不过是一个供程序操作的存储区的名字。
在 C# 中,变量是用于存储和表示数据的标识符,在声明变量时,您需要指定变量的类型,并且可以选择性地为其分配一个初始值。
就像这个样子:int number_a = 10; 或者 int number_b;
在 C# 中,每个变量都有一个特定的类型,类型决定了变量的内存大小和布局,范围内的值可以存储在内存中,可以对变量进行一系列操作。
C# 中提供的基本的值类型大致可以分为以下几类:
类型 | 举例 |
---|---|
整数类型 | sbyte、byte、short、ushort、int、uint、long、ulong 和 char |
浮点型 | float, double |
十进制类型 | decimal |
布尔类型 | true 或 false 值,指定的值 |
空字符串 | string |
空类型 | 可为空值的数据类型 |
C# 允许定义其他值类型的变量 , 比如 enum,也允许定义引用类型变量,比如 class。
变量的定义
代码演示:
int i, j, k;
char c, ch;
float f, salary;
double d;
变量的初始化
int i = 100;
变量的命名规则
在 C# 中,变量的命名需要遵循一些规则:
- 变量名可以包含字母、数字和下划线。
- 变量名必须以字母或下划线开头。
- 变量名区分大小写。
- 避免使用 C# 的关键字作为变量名。
代码演示:
int myVariable = 10;
string _userName = "John";
C# 中的变量初始化
变量通过在等号后跟一个常量表达式进行初始化(赋值)。初始化的一般形式为:
int d = 3, f = 5; /* 初始化 d 和 f. */
byte z = 22; /* 初始化 z. */
double pi = 3.14159; /* 声明 pi 的近似值 */
char x = 'x'; /* 变量 x 的值为 'x' */
变量可以在声明时被初始化(指定一个初始值)。初始化由一个等号后跟一个常量表达式组成
接收来自用户的值
System 命名空间中的 Console 类提供了一个函数 ReadLine() ,用于接收来自用户的输入,并把它存储到一个变量中。
代码演示:
int num;
num = Convert.ToInt32(Console.ReadLine());
函数 Convert.ToInt32() 把用户输入的数据转换为 int 数据类型,因为 Console.ReadLine() 只接受字符串格式的数据。