数据类型 在 C# 中,变量分为以下类型:
值类型 值类型复制时直接拷贝。如果值类型的数据成员中包括引用类型时,引用类型只会浅拷贝。
T?
是一个可以为 T
或者=null= 的值类型,类似 optional
。
简单类型 C# 内置了下面几种类型,也叫做简单类型:
对于简单类型,支持下面的操作:
支持字面量声明值,如 ‘A’ 是 char 类型的字面量 可以用 const
声明简单类型常量,其它的类型不行 简单类型的常量表达式在编译期执行 C# 的 char 类型是 Unicode UTF-16 ,每个 char 大小为 16 bit
枚举类型 Copy 1
2
3
4
5
6
enum Season {
Spring,
Summer,
Autumn,
Winter
}
也可以指定枚举成员的具体类型
Copy 1
2
3
4
5
6
enum Season : ushort {
Spring,
Summer,
Autumn,
Winter
}
更多请看:枚举类型
结构体类型 结构体是值类型,可以有数据和方法, 相关文档:结构体
Copy 1
2
3
4
5
6
7
8
9
10
11
12
13
public struct Coords
{
public Coords(double x, double y)
{
X = x;
Y = y;
}
public double X { get ; }
public double Y { get ; }
public override string ToString() => $"({X}, {Y})" ;
}
readonly
结构体,结构体的所有成员是不可变的。
Copy 1
2
3
4
5
6
7
8
9
10
11
12
13
public readonly struct Coords
{
public Coords(double x, double y)
{
X = x;
Y = y;
}
public double X { get ; init ; }
public double Y { get ; init ; }
public override string ToString() => $"({X}, {Y})" ;
}
方法也可以称为 readonly
的, 重载的方法也可加 readonly
Copy 1
2
3
4
5
6
public readonly double Sum()
{
return X + Y;
}
public readonly override string ToString() => $"({X}, {Y})" ;
Tuple 类型 相关文档:Tuple 类型
Copy 1
2
3
4
5
6
7
8
9
(double , int ) t1 = (4.5 , 3 );
Console.WriteLine($"Tuple with elements {t1.Item1} and {t1.Item2}." );
// Output:
// Tuple with elements 4.5 and 3.
(double Sum, int Count) t2 = (4.5 , 3 );
Console.WriteLine($"Sum of {t2.Count} elements is {t2.Sum}." );
// Output:
// Sum of 3 elements is 4.5.
Nullable 类型 类型 Optional, 值可以为 null ,相关文档:Nullable
Copy 1
2
3
4
5
6
7
8
9
10
double? pi = 3.14 ;
char? letter = 'a' ;
int m2 = 10 ;
int? m = m2;
bool? flag = null ;
// An array of a nullable value type:
int? [] arr = new int? [10 ];
可以用 is
或者 hasValue
检测值
Copy 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int? a = 42 ;
if (a is int valueOfA)
{
Console.WriteLine($"a is {valueOfA}" );
}
else
{
Console.WriteLine("a does not have a value" );
}
// Output:
// a is 42
int? b = 10 ;
if (b.HasValue)
{
Console.WriteLine($"b is {b.Value}" );
}
else
{
Console.WriteLine("b does not have a value" );
}
// Output:
// b is 10
引用类型 引用类型的存储数据的引用,赋值时执行浅拷贝。
C# 中可以声明引用类型的关键字:class, interface, delegate, record
使用 class
关键字声明类:
Copy 1
2
3
4
5
class TestClass
{
// Methods, properties, fields, events, delegates
// and nested classes go here.
}
使用 interface
定义接口约束:
Copy 1
2
3
4
5
6
7
8
9
10
11
12
13
interface ISampleInterface
{
void SampleMethod();
}
class ImplementationClass : ISampleInterface
{
// Explicit interface member implementation:
void ISampleInterface.SampleMethod()
{
// Method implementation.
}
}
使用 record
定义一个引用类型,编译器会为它提供一些默认的机制,如相等比较是值相等,定义输出格式。
Copy 1
2
3
4
5
public record Person
{
public string FirstName { get ; set ; }
public string LastName { get ; set ; }
};
内置 object 类型 object
是 System.Object
的别名,在 C# 的类型系统中,所有类型都直接或间接继承自 object
。
当一个值类型转换成 object
类型,叫装箱,当一个 object
类型的值转成值类型,叫拆箱。
string 类型 string
类型是 System.String
的别名,string 是引用类型,但是它的 \=\= 和 !\= 操作是比较值
Copy 1
2
3
4
5
6
string a = "hello" ;
string b = "h" ;
// Append to contents of 'b'
b += "ello" ;
Console.WriteLine(a == b);
Console.WriteLine(object .ReferenceEquals(a, b));
string
对象内的字符串是不可变的,用 +
会创建新的 string
对象。
Copy 1
string a = "good " + "morning" ;
[]
操作符可以访问字符串中的字符。
Copy 1
2
string str = "test" ;
char x = str[2 ]; // x = 's';
字符串字面量前加 @ 就是原生字符串,内部可以不用转义。
Copy 1
@"c:\Docs\Source\a.txt" // rather than "c:\\Docs\\Source\\a.txt"
如果字符串内部有双引号,用两个双引号表示。
Copy 1
@"""Ahoy!"" cried the captain." // "Ahoy!" cried the captain.
delegate 类型 delegate
类型的声明类似方法签名,它有返回值和任意数量的参数。
Copy 1
2
public delegate void MessageDelegate(string message);
public delegate int AnotherDelegate(MyType m, long num);
一个 delegate
是引用类型,可以用来表示命名或者匿名方法,类似 C++ 中的函数指针。
dynamic 类型 dynamic
类型的变量可以绕过编译期类型检查,而在运行时解析。
指针类型 指针类型只能在 unsafe
代码中使用。
Copy 1
2
type* identifier;
void * identifier; //allowed but not recommended
控制流程 条件判断 使用 if-else 语句
Copy 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Console.Write("Enter a character: " );
char ch = (char )Console.Read();
if (Char.IsUpper(ch))
{
Console.WriteLine("The character is an uppercase letter." );
}
else if (Char.IsLower(ch))
{
Console.WriteLine("The character is a lowercase letter." );
}
else if (Char.IsDigit(ch))
{
Console.WriteLine("The character is a number." );
}
else
{
Console.WriteLine("The character is not alphanumeric." );
}
//Sample Input and Output:
//Enter a character: E
//The character is an uppercase letter.
//Enter a character: e
//The character is a lowercase letter.
//Enter a character: 4
//The character is a number.
//Enter a character: =
//The character is not alphanumeric.
可以使用 switch 语句
Copy 1
2
3
4
5
6
7
8
9
10
11
12
switch (caseSwitch)
{
case 1 :
Console.WriteLine("Case 1" );
break ;
case 2 :
Console.WriteLine("Case 2" );
break ;
default :
Console.WriteLine("Default case" );
break ;
}
循环语句 for
语句
Copy 1
2
3
4
5
6
for (int i = 0 ; i < 3 ; i++)
{
Console.Write(i);
}
// Output:
// 012
foreach
语句
Copy 1
2
3
4
5
6
7
var fibNumbers = new List<int > { 0 , 1 , 1 , 2 , 3 , 5 , 8 , 13 };
foreach (int element in fibNumbers)
{
Console.Write($"{element} " );
}
// Output:
// 0 1 1 2 3 5 8 13
await foreach
语句,消费异步数据流
Copy 1
2
3
4
await foreach (var item in GenerateSequenceAsync())
{
Console.WriteLine(item);
}
使用 var
在编译器推导类型。
do while
语句
Copy 1
2
3
4
5
6
7
8
int n = 0 ;
do
{
Console.Write(n);
n++;
} while (n < 5 );
// Output:
// 01234
while
语句
Copy 1
2
3
4
5
6
7
8
int n = 0 ;
while (n < 5 )
{
Console.Write(n);
n++;
}
// Output:
// 01234
跳转语句 break
跳出最近的循环或 switch
语句。
Copy 1
2
3
4
5
6
7
8
for (int i = 1 ; i <= 100 ; i++)
{
if (i == 5 )
{
break ;
}
Console.WriteLine(i);
}
continue
马上下一次迭代。
Copy 1
2
3
4
5
6
7
8
for (int i = 1 ; i <= 10 ; i++)
{
if (i < 9 )
{
continue ;
}
Console.WriteLine(i);
}
goto
语句跳转到一个标签:
return
终止方法执行,如果在 try
块里,会执行 finally
块 。
异常语句 throw
抛出异常,终止当前程序执行
Copy 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
using System ;
namespace Throw2
{
public class NumberGenerator
{
int [] numbers = { 2 , 4 , 6 , 8 , 10 , 12 , 14 , 16 , 18 , 20 };
public int GetNumber(int index)
{
if (index < 0 || index >= numbers.Length)
{
throw new IndexOutOfRangeException();
}
return numbers[index];
}
}
throw
可以作为表达式
Copy 1
2
string arg = args.Length >= 1 ? args[0 ] :
throw new ArgumentException("You must supply an argument" );
异常可以通过 throw
重新抛出
Copy 1
2
3
4
5
6
7
8
try
{
return Value[0 ];
}
catch (NullReferenceException e)
{
throw ;
}
try-catch-finally
捕获异常
Copy 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class EHClass
{
void ReadFile(int index)
{
// To run this code, substitute a valid path from your local machine
string path = @"c:\users\public\test.txt" ;
System.IO.StreamReader file = new System.IO.StreamReader(path);
char [] buffer = new char [10 ];
try
{
file.ReadBlock(buffer, index, buffer.Length);
}
catch (System.IO.IOException e)
{
Console.WriteLine("Error reading from {0}. Message = {1}" , path, e.Message);
}
finally
{
if (file != null )
{
file.Close();
}
}
// Do something with buffer...
}
}
其它知识 region 和 endregion region 和 endregion 表示一块区域,在 VS 可以折叠起来,方便查看。