C#(读作"C Sharp")是一种现代的、通用的面向对象编程语言,由微软公司开发。它结合了C和C++的强大特性,并去掉了一些复杂性,使得开发者可以更加高效地编写代码。
一、入坑C#
(一) 安装和设置
首先,确保你的计算机上安装了 .NET SDK。这个SDK包含了编译和运行C#程序所需的工具。
提供一种在线运行哦,如果你不是为了写项目,只是为了来学语法的,你可以使用在线运行的方式,就不用安装环境啦。
(二) 第一个C#程序
打开你喜欢的文本编辑器(如Visual Studio Code、Visual Studio等),创建一个新文件,命名为 HelloWorld.cs
。
using System; // 引入System命名空间,包含了Console类等核心功能
class Program
{
static void Main() // 主方法,程序的入口点
{
Console.WriteLine("Hello, World!"); // 在控制台输出Hello, World!
}
}
(三) 编译和运行
打开命令行工具(如PowerShell或终端),进入到保存 HelloWorld.cs
文件的目录。运行以下命令编译和运行程序:
dotnet run HelloWorld.cs
你应该会看到输出:
Hello, World!
恭喜!你已经成功运行了你的第一个C#程序。
(四) 在线运行
二、基本语法和结构
(一) 变量和数据类型
在 C# 中,变量分为以下几种类型:
- 值类型(Value types)
- 引用类型(Reference types)
- 指针类型(Pointer types)
1. 值类型
值类型变量可以直接分配给一个值。它们是从类 System.ValueType
中派生的。
值类型直接包含数据。比如 int
、char
、float
,它们分别存储 数字、字符、浮点数。
类型 |
描述 |
范围 |
默认值 |
bool |
布尔值 |
True 或 False |
False |
byte |
8 位无符号整数 |
0 到 255 |
0 |
char |
16 位 Unicode 字符 |
U +0000 到 U +ffff |
'\0' |
decimal |
128 位精确的十进制值,28-29 有效位数 |
(-7.9 x 1028 到 7.9 x 1028) / 100 到 28 |
0.0M |
double |
64 位双精度浮点型 |
(+/-)5.0 x 10-324 到 (+/-)1.7 x 10308 |
0.0D |
float |
32 位单精度浮点型 |
-3.4 x 1038 到 + 3.4 x 1038 |
0.0F |
int |
32 位有符号整数类型 |
-2,147,483,648 到 2,147,483,647 |
0 |
long |
64 位有符号整数类型 |
-9,223,372,036,854,775,808 到 9,223,372,036,854,775,807 |
0L |
sbyte |
8 位有符号整数类型 |
-128 到 127 |
0 |
short |
16 位有符号整数类型 |
-32,768 到 32,767 |
0 |
uint |
32 位无符号整数类型 |
0 到 4,294,967,295 |
0 |
ulong |
64 位无符号整数类型 |
0 到 18,446,744,073,709,551,615 |
0 |
ushort |
16 位无符号整数类型 |
0 到 65,535 |
0 |
在C#中,变量需要显式声明其类型。例如:
int age = 25;
string name = "悟解";
double salary = 2500.50;
bool isEmployed = true;
2. 引用类型
当使用引用类型时,变量不直接包含实际数据,而是包含对数据所在内存位置的引用。换句话说,它们指向内存中的一个位置。多个变量可以指向同一个内存位置。如果一个变量修改了这个位置的数据,其他变量也会自动反映出这些值的变化。内置的引用类型包括:object、string。
一、对象类型
对象类型(Object Type)是C#通用类型系统中所有数据类型的最终基类。Object
类型是System.Object
类的别名。因此,对象类型可以存储任何其他类型(值类型、引用类型、预定义类型或用户定义类型)的值。但在分配值之前,需要进行类型转换。
当将值类型转换为对象类型时,这称为装箱(boxing);反之,当对象类型转换为值类型时,则称为拆箱(unboxing)。
object obj;
object obj = 100; // 装箱
int num = (int)obj; // 拆箱
Console.WriteLine(num); // 输出:100
二、动态类型(Dynamic Type)
动态类型变量可以存储任何类型的值,并且其类型检查是在运行时而非编译时进行的。
声明动态类型变量的语法如下:
dynamic <variable_name> = value;
例如:
dynamic d = 20;
动态类型与对象类型相似,但是对象类型变量的类型检查是在编译时进行的,而动态类型变量的类型检查是在运行时进行的。
三、字符串(String)类型
字符串(String)类型允许你存储任意字符串值。它是System.String
类的别名,从Object类型派生而来。字符串类型的值可以通过两种方式分配:使用引号和@引号。
// 使用双引号分配字符串值给变量
string str1 = "悟解";
// 使用@符号来创建逐字字符串,转义字符会被当作普通字符处理
string str2 = @"C:\悟解";
// @字符串可以包含任意换行符和缩进空格
string str3 = @"<script type=""text/javascript"">
<!--悟解来学C#啦!!!-->
</script>";
// 字符串的长度包括换行符和缩进空格
int str3Length = str3.Length;
四、指针类型(Pointer types)
允许存储另一种类型的内存地址。在C#中,指针与C或C++中的指针功能类似。
char* c;
int* i;
这些声明定义了分别指向字符(char)和整数(int)类型的指针变量。
3. C# 类型转换详解
在 C# 编程中,类型转换是将一个数据类型的值转换为另一个数据类型的过程。C# 提供了两种主要的类型转换方式:隐式类型转换和显式类型转换(也称为强制类型转换)。
一、隐式类型转换
隐式类型转换是由编译器自动完成的转换过程,不需要显示指定类型转换操作。这种转换通常发生在从较小范围数据类型向较大范围数据类型(小->大)的转换中,它是安全的不会导致数据丢失。
例如,将一个整数赋值给一个长整数或者将一个浮点数赋值给一个双精度浮点数都属于隐式类型转换。
byte a = 10;
int i = a; // 隐式转换,不需要显式转换,编译器会自动完成类型转换
二、显式类型转换
显式类型转换(或称为强制类型转换)需要程序员在代码中明确指定转换操作,它发生在从较大范围数据类型向较小范围数据类型(大->小)的转换中,或者在对象类型之间的转换中。显式类型转换可能会导致数据丢失,因此需要谨慎使用。
double d = 3.14;
int i = (int)d; // 强制从 double 到 int,数据可能损失小数部分
另一个常见的显式类型转换是将整数转换为字符串:
int i = 123;
string s = i.ToString(); // 将 int 转换为字符串
上述代码中,i.ToString()
方法将 i
的整数值转换为其字符串表示形式。
三、类型转换
使用 Convert
类、Parse
方法和 TryParse
方法进行类型转换是在 C# 中处理数据类型转换常见且有效的方式。
(一) 使用 Convert 类
Convert
类提供了方便的静态方法,用于在各种基本数据类型之间进行转换。
这些方法都定义在 System.Convert
类中,使用时需要包含 System 命名空间。它们提供了一种安全的方式来执行类型转换,因为它们可以处理 null值,并且会抛出异常,如果转换不可能进行。
方法 |
描述 |
ToBoolean |
如果可能的话,把类型转换为布尔型。 |
ToByte |
把类型转换为字节类型。 |
ToChar |
如果可能的话,把类型转换为单个 Unicode 字符类型。 |
ToDateTime |
把类型(整数或字符串类型)转换为 日期-时间 结构。 |
ToDecimal |
把浮点型或整数类型转换为十进制类型。 |
ToDouble |
把类型转换为双精度浮点型。 |
ToInt16 |
把类型转换为 16 位整数类型。 |
ToInt32 |
把类型转换为 32 位整数类型。 |
ToInt64 |
把类型转换为 64 位整数类型。 |
ToSbyte |
把类型转换为有符号字节类型。 |
ToSingle |
把类型转换为小浮点数类型。 |
ToString |
把类型转换为字符串类型。 |
ToType |
把类型转换为指定类型。 |
ToUInt16 |
把类型转换为 16 位无符号整数类型。 |
ToUInt32 |
把类型转换为 32 位无符号整数类型。 |
ToUInt64 |
把类型转换为 64 位无符号整数类型。 |
string str = "123";
int num = Convert.ToInt32(str);
在上面的示例中,将字符串 "123"
转换为整数类型 int
,并赋值给变量 num
。
(二) 使用 Parse 方法
Parse
方法用于将字符串转换为对应的数值类型。如果字符串格式不正确,将会抛出异常。
方法 |
描述 |
|
将字符串解析为 |
|
将字符串解析为 |
|
将字符串解析为 |
|
将字符串解析为 |
|
将字符串解析为 |
|
将字符串解析为 |
|
将字符串解析为 |
|
将字符串解析为 |
|
将字符串解析为 |
|
将字符串解析为 |
|
将字符串解析为 |
|
将字符串解析为 |
|
将字符串解析为 |
|
将字符串解析为 |
string str = "6.66";
double d = double.Parse(str);
在上面的示例中,将字符串 "6.66"
转换为双精度浮点数类型 double
,并赋值给变量 d
。
(三) 使用 TryParse 方法
TryParse
方法类似于 Parse
,但不会抛出异常。它返回一个布尔值,指示转换是否成功,并通过 out
参数返回转换后的值。
方法 |
描述 |
|
尝试将字符串解析为 |
|
尝试将字符串解析为 |
|
尝试将字符串解析为 |
|
尝试将字符串解析为 |
|
尝试将字符串解析为 |
|
尝试将字符串解析为 |
|
尝试将字符串解析为 |
|
尝试将字符串解析为 |
|
尝试将字符串解析为 |
|
尝试将字符串解析为 |
|
尝试将字符串解析为 |
|
尝试将字符串解析为 |
|
尝试将字符串解析为 |
|
尝试将字符串解析为 |
string str = "123.45";
double d;
bool success = double.TryParse(str, out d);
if (success) {
Console.WriteLine("转换成功: " + d);
} else {
Console.WriteLine("转换失败");
}
(四) 自定义类型转换
在C#中,你可以通过定义特定的运算符重载方法来实现自定义类型转换。这些方法允许你在不同类型之间进行显式或隐式转换。在C#中,有两种类型转换的关键字:
- implicit (隐式):隐式转换方法允许编译器在不需要显式转换的情况下自动进行类型转换。通常用于从小范围类型到大范围类型的转换,或者在没有数据丢失的情况下进行转换。使用
implicit
关键字定义的转换方法,必须满足安全转换的条件,即不能造成数据丢失或精度降低。 - explicit (显式):显式转换方法要求在代码中明确地使用强制类型转换运算符来指定转换的方式。这种方式适用于可能会造成数据丢失的转换,或者在语义上不太明确的转换操作。使用
explicit
关键字定义的转换方法,需要通过强制类型转换来调用。
让我们通过一个简单的例子来说明如何在自定义类型中定义这两种转换方法。
using System;
// 自定义温度类
public class Temperature {
public double Celsius { get; }
// 构造函数
public Temperature(double celsius) {
Celsius = celsius;
}
// 隐式转换:从摄氏度到华氏度
public static implicit operator Fahrenheit(Temperature t) {
double fahrenheit = t.Celsius * 9 / 5 + 32;
return new Fahrenheit(fahrenheit);
}
// 显式转换:从摄氏度到开尔文
public static explicit operator Kelvin(Temperature t) {
double kelvin = t.Celsius + 273.15;
return new Kelvin(kelvin);
}
}
// 华氏度类
public class Fahrenheit {
public double Value { get; }
public Fahrenheit(double value) {
Value = value;
}
}
// 开尔文类
public class Kelvin {
public double Value { get; }
public Kelvin(double value) {
Value = value;
}
}
class Program {
static void Main()