修饰词关键字
修饰词关键字是特定的关键字,指示谁可以修改类型和类型成员。修饰符允许或阻止程序的某些部分被其他部分修改。
| 修饰词关键字 | ||||||
|---|---|---|---|---|---|---|
| abstract | async | const | event | extern | new | override |
| sealed | static | unsafe | virtual | volatile | readonly | partial |
abstract 抽象的
abstract 用于声明虚类,指示某个类只能是其他类的基类。
sealed 密封的
指定类不能作为基类被继承,或方法不能被重写。
async 异步的
指定方法为异步方法。
static 静态的
声明静态类,类型本身只含有静态成员,不能被实例化。
const 常量
常量和变量都是用来存储数据的容器,在定义时都需要指明数据类型,常量(constant)中存放的值不允许改变。
语法
访问修饰符 const 数据类型 常量名 = 值
Tips: 需要注意的是,在定义常量时必须为其赋值,因为不赋值的话以后就再也不能赋值了。另外,也可以同时定义多个常量。const字段不能通过引用传递,也不能在表达式中作为左值出现。
示例
// 同时声明多个相同类型的常量
const int months = 12;
weeks = 52;
days = 265;
unsafe 不安全的
允许直接操作内存地址、指针等底层资源。这是 C# 的一种特殊功能,用于提供对计算机硬件的低级访问,通常是在需要高性能或者与硬件交互时使用,但也可能带来安全性问题,因此需要谨慎使用。
event 事件
event 声明一个事件。
virtual 虚拟的
virtual 用于定义可以在派生类中重写的方法或属性。
-
使方法、属性或事件可以被重写。派生类可以覆盖基类中的虚方法,以实现多态性。
-
只有类中的虚方法或属性才能在派生类中使用
override关键字进行重写。
示例
public class A
{
public virtual void input {
Console.WriteLine("A")
}
}
public class B : A
{
public override void input {
Console.WriteLine("B")
}
}
extern 外面的
extern:声明外部方法,通常与 DllImport 一起用于调用外部库中的方法。
- 声明一个方法是在外部实现的,这意味着方法的实现不在 C# 代码中,而是在外部库中。
- 通常与
DllImport特性一起使用,用来调用外部的 C 或 C++ 函数。
示例
using System;
using System.Runtime.InteropServices;
class Program
{
// 使用 extern 和 DllImport 调用外部 DLL 函数
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int MessageBox(IntPtr hWnd, String text, String caption, uint type);
static void Main()
{
MessageBox(IntPtr.Zero, "Hello, world!", "C# P/Invoke", 0);
}
}
volatile 易变的
volatile:指示字段在多线程环境中可能被多个线程修改,防止编译器优化缓存。
-
防止编译器优化:用于多线程环境,确保字段的值不会被缓存,以便每次都能读取到最新的值。
-
多线程同步:通常与多线程编程结合使用,确保不同线程对该字段的操作是同步的。
示例
public class Example
{
private volatile bool flag;
public void Thread1()
{
flag = true; // 写操作
}
public void Thread2()
{
if (flag)
{
Console.WriteLine("Flag is true");
}
}
}
new 新的
new:用于隐藏基类成员或创建类的实例。
- 隐藏继承的成员:在派生类中使用
new来隐藏基类中具有相同名称的成员(例如方法、属性、字段等)。这与virtual和override不同,new并不会使成员变成可重写的,而是隐藏基类成员的实现。 - 创建对象实例:用于创建类的实例,分配内存并初始化对象。
- 泛型约束:用于在泛型声明中约束可能用作类型参数的参数的类型。
{
public class BaseClass
{
public void Display()
{
Console.WriteLine("BaseClass Display");
}
}
public class DerivedClass : BaseClass
{
// 使用 new 关键字隐藏基类方法
public new void Display()
{
Console.WriteLine("DerivedClass Display");
}
}
public class Program
{
static void Main(string[] args)
{
BaseClass obj = new DerivedClass();
obj.Display(); // 输出:BaseClass Display,隐藏的成员在运行时不会被调用
DerivedClass derivedClass = new DerivedClass();
BaseClass baseClass = new BaseClass();
derivedClass.Display(); // 输出:DerivedClass Display
baseClass.Display(); // 输出:BaseClass Display
}
}
}
readonly 只读的
readonly 指示一个域只能在声明时以同类的内部被赋值。
override 重载的
override 对于基类继承成员的新实现。
抽象类(abstract class)中的抽象方法(abstract void)在继承后都需要重载(override void)。
partial 部分的
部分在整个同一程序集中定义分部类、结构和方法。
Partial关键词定义的类可以在多个地方被定义,最后编译的时候会被当作一个类来处理。
常见的有 winform 中的design文件和form文件的类名相同,但是是两个文件都会用到partial关键字。
访问修饰符关键字
访问修饰符应用于类,方法,属性,字段和其他成员的声明。它们定义了类及其成员的可访问性。
| 访问修饰符 | ||||
|---|---|---|---|---|
| public | private | internal | protected | protected internal |
public 公共的
public 公有访问,不受任何限制。
private 私有的
private 私有访问,只限于本类成员访问,子类、实例都不能访问。
internal 内部的
internal 内部访问,只限于本项目内访问,其他不能访问。
Tips:如果没有指定修饰符,这是默认访问修饰。
protected 受保护的
protected 保护访问,只限于本类和子类访问,实例不能访问。
protected internal 受保护的内部成员
protected internal 内部保护访问,只限于本项目或者子类访问,其他不能访问。
语句关键字
| 语句关键字 | |||||
|---|---|---|---|---|---|
| 条件语句 | if | else | else if | switch | case |
| 循环控制 | for | foreach | while | do | yield |
| 跳转控制 | break | continue | goto | return | throw |
| 异常处理 | try | catch | finally | ||
| 异步编程 | async | await | |||
| 资源管理 | using | lock |
switch case
switch (day)
{
case 1:
Console.WriteLine("Monday");
break;
case 2:
Console.WriteLine("Tuesday");
break;
default:
Console.WriteLine("Invalid day");
break;
}
goto
int x = 10;
start:
if (x > 0)
{
Console.WriteLine(x);
x--;
goto start; // 跳回 start 标签
}
async await
public async Task ProcessDataAsync()
{
await Task.Delay(1000); // 异步等待 1 秒
Console.WriteLine("Process completed.");
}
lock
lock 语句用于确保某一段代码在任意时刻只有一个线程能访问它,用于多线程同步。
private readonly object _lock = new object();
public void UpdateResource()
{
lock (_lock)
{
// 只有一个线程能进入此代码块
}
}
方法参数关键字
| 方法参数关键字 | ||||
|---|---|---|---|---|
| ref | out | in | params | this |
ref 引用
ref 关键字用于将参数按引用传递给方法。与常规的值传递不同,使用 ref 参数时,方法可以修改传入的参数,并且这些修改在方法返回后仍然有效。
-
在方法声明和调用时都需要使用
ref。 -
参数必须在调用方法之前被初始化。
示例
class Program
{
static void Increment(ref int x)
{
x++; // 增加 x 的值
}
static void Main()
{
int a = 5;
Increment(ref a); // 将 a 作为引用传递
Console.WriteLine(a); // 输出:6
}
}
out 输出
out 关键字与 ref 类似,也是用于按引用传递参数。但与 ref 不同的是,out 参数在传入方法之前不需要初始化。out 参数通常用于方法返回多个值。
-
在方法声明和调用时都需要使用
out。 -
在方法内部,必须给
out参数赋值,否则会报错。
示例
class Program
{
static void TryParseInt(string input, out int result)
{
if (!int.TryParse(input, out result))
{
result = 0; // 如果转换失败,返回 0
}
}
static void Main()
{
string str = "123";
int number;
TryParseInt(str, out number); // 使用 out 参数
Console.WriteLine(number); // 输出:123
}
}
in 输入
in 关键字用于按引用传递参数,但它指定参数是只读的,即方法无法修改它的值。它的作用类似于 ref,但在方法内部不能修改 in 参数。
- 在方法声明和调用时都需要使用
in。 in参数传递时不允许修改其值。
class Program
{
static void Display(in int x)
{
// x = 10; // 编译错误,不能修改 in 参数
Console.WriteLine(x); // 输出:5
}
static void Main()
{
int num = 5;
Display(in num); // 使用 in 参数
}
}
params 多个参数
params 关键字用于指定一个方法接受可变数量的参数。参数类型必须是数组类型,可以传递零个或多个参数。
- 只有一个参数可以使用
params。 params必须是方法的最后一个参数。
class Program
{
static void PrintNumbers(params int[] numbers)
{
foreach (var num in numbers)
{
Console.WriteLine(num);
}
}
static void Main()
{
PrintNumbers(1, 2, 3); // 可以传递任意数量的参数
PrintNumbers(5, 6); // 也可以传递零个或多个参数
}
}
this 这个
this 关键字可以用于扩展方法(extension methods)的定义。扩展方法允许在不修改原始类型的情况下向现有类型添加新功能。
语法:
- 扩展方法必须是静态方法,并且第一个参数使用
this关键字,表示扩展的方法是作用于该类型的实例。
public static class StringExtensions
{
// 扩展方法:为 string 类型添加一个 Reverse 方法
public static string Reverse(this string str)
{
char[] charArray = str.ToCharArray();
Array.Reverse(charArray);
return new string(charArray);
}
}
class Program
{
static void Main()
{
string text = "hello";
Console.WriteLine(text.Reverse()); // 输出:olleh
}
}
命名空间关键字
这些关键字与名称空间和相关运算符一起应用。
| 命名空间关键字 | ||
|---|---|---|
| using | extern alias | namespace |
using 引用命名空间
using System;
如果不引用命名空间的化,想使用System中的Console类只能使用如下方法
System.Console.Write("123")
如果引用了命名空间只需要写成
using System;
namespace consoleApp
{
class Program
{
static void Main(string[] args)
{
Console.Write("123");
Console.Write("abc");
}
}
}
extern alias 外部别名
extern alias 是一个用于引用外部程序集(通常是 DLL)并为其指定别名的关键字。这个关键字在涉及到程序集冲突时非常有用,尤其是在引用不同版本的同一个程序集时。
通常,extern alias 被用来解决程序集重定向冲突,或者在同一个项目中引用多个版本的相同程序集。
-
使用
extern alias时,你需要在引用的 DLL 上指定别名,并在代码中使用该别名来访问该程序集的类型。 -
这种情况一般发生在当项目需要引用多个版本的同一个程序集,或者引用的程序集与其他程序集有重名类型时。
<ItemGroup>
<Reference Include="MyLibrary">
<HintPath>..\lib\MyLibrary_v1.dll</HintPath>
<Aliases>v1</Aliases>
</Reference>
<Reference Include="MyLibrary">
<HintPath>..\lib\MyLibrary_v2.dll</HintPath>
<Aliases>v2</Aliases>
</Reference>
</ItemGroup>
extern alias v1;
extern alias v2;
using System;
class Program
{
static void Main()
{
v1::MyLibrary.MyClass obj1 = new v1::MyLibrary.MyClass();
v2::MyLibrary.MyClass obj2 = new v2::MyLibrary.MyClass();
}
}
解决程序集冲突:当多个程序集引用了相同的类型,但这些程序集的版本不同,使用 extern alias 可以区分不同的程序集。
多版本程序集支持:可以在同一应用程序中同时使用多个版本的同一个程序集。
namespace 命名空间
是只标识符的各种可见范围,只是起到标识的作用,把需要的内容放在一起,细化管理。也可以定义自己的命名空间。
namespace Hello
{
}
运算符关键字
运算符关键字执行其他操作。
| 运算符关键词 | ||||
|---|---|---|---|---|
| as | operator | is | sizeof | typeof |
| stackalloc | checked | unchecked | implicit | explicit |
as 作为
as 关键字用于类型转换,它尝试将对象转换为指定类型。如果转换成功,返回转换后的对象;如果转换失败,则返回 null(仅适用于引用类型或可空值类型)。
operator
operator 关键字用于定义运算符重载(Operator Overloading)。运算符重载允许你为用户自定义的类型定义特定的运算符行为,使得这些类型的对象能够参与基本的运算符操作(如 +、-、* 等)。
-
operator关键字用于声明重载运算符的方法。 -
这些方法必须是静态的,并且返回运算符结果的类型。
public class Point
{
public int X { get; set; }
public int Y { get; set; }
// 运算符重载:+ 运算符
public static Point operator +(Point p1, Point p2)
{
return new Point { X = p1.X + p2.X, Y = p1.Y + p2.Y };
}
public override string ToString()
{
return $"({X}, {Y})";
}
}
class Program
{
static void Main()
{
Point p1 = new Point { X = 1, Y = 2 };
Point p2 = new Point { X = 3, Y = 4 };
// 使用重载的 + 运算符
Point p3 = p1 + p2;
Console.WriteLine(p3); // 输出: (4, 6)
}
}
常用的运算符重载:
- 算数运算符:
+,-,*,/ - 关系运算符:
<,>,==,!= - 逻辑运算符:
&&,|| - 类型转换运算符:
explicit,implicit
is 是
is 关键字用于检查对象是否是某个类型的实例。它返回一个布尔值,表示对象是否可以被转换为指定类型。
is 关键字常用于类型检查。C# 7.0 以后,它也可以在 is 表达式中直接进行类型转换:
{
object obj = "Hello";
if (obj is string str){
Console.WriteLine(str);
}
}
sizeof 大小
sizeof 关键字用于获取一个数据类型在内存中占用的字节数。sizeof 只能用于已知大小的值类型(如整数、浮点数等),不能用于引用类型。
typeof 类型
typeof 关键字用于获取类型的 Type 对象。它返回一个表示类型的 Type 实例,通常用于反射。
Type type = typeof(int);
Console.WriteLine(type); // 输出: System.Int32
stackalloc 在堆栈上分配内存块
stackalloc 关键字在 C# 中用于在栈上分配内存。它通常与 unsafe 代码一起使用,因为它涉及对内存的直接操作。stackalloc 为一个指定大小的内存块分配空间,并返回一个指向该内存块的指针。由于是栈上分配的内存,所以它的生命周期仅限于当前方法的作用域,一旦方法返回,该内存将自动释放。
-
stackalloc分配的内存位于栈上,而不是堆上。 -
该内存区域在方法返回后自动销毁。
-
通常用于需要快速分配小块内存的场景。
-
需要启用
unsafe代码,因为它涉及指针操作。
class Program
{
public unsafe static void Main()
{
// 使用 stackalloc 分配一个大小为 10 的 int 数组
int* numbers = stackalloc int[10];
for (int i = 0; i < 10; i++)
{
numbers[i] = i * 2;
Console.WriteLine(numbers[i]);
}
}
}
checked
checked 关键字用于启用溢出检查。它确保在进行算术运算时,如果发生溢出(例如 int 类型超过其最大值),会抛出 OverflowException 异常。
int a = int.MaxValue;
try
{
int result = checked(a + 1); // 会抛出 OverflowException
}
catch (OverflowException ex)
{
Console.WriteLine(ex.Message); // 输出: Arithmetic operation resulted in an overflow.
}
unchecked
unchecked 关键字用于禁用溢出检查,即使在进行算术运算时发生溢出,也不会抛出异常。它可以显式地告诉编译器不对算术溢出进行检查。
int a = int.MaxValue;
int result = unchecked(a + 1); // 不会抛出异常,结果为溢出后的值
Console.WriteLine(result); // 输出: -2147483648
unchecked 通常用于性能优化,尤其是在对溢出不关心的情况下。
implicit 隐式
implicit 用于定义隐式类型转换。隐式转换是指不需要显式地调用转换操作符,编译器会自动根据上下文进行转换。当你定义了隐式转换时,编译器会在合适的地方自动执行转换,无需用户干预。
using System;
class TimeSpan
{
public int Seconds { get; set; }
public TimeSpan(int seconds)
{
Seconds = seconds;
}
// 隐式转换:TimeSpan -> int
public static implicit operator int(TimeSpan time)
{
return time.Seconds;
}
}
class Program
{
static void Main()
{
TimeSpan time = new TimeSpan(3600); // 1 小时 = 3600 秒
int seconds = time; // 隐式转换为 int
Console.WriteLine(seconds); // 输出: 3600
}
}
explicit 显式
explicit 用于定义显式类型转换。显式转换是指必须使用强制类型转换语法(即 (TargetType))才能进行转换,编译器不会自动执行转换。如果没有显式转换操作符,或者转换不合适,编译器会报错。
class Temperature
{
public double Celsius { get; set; }
public Temperature(double celsius)
{
Celsius = celsius;
}
// 显式转换:Temperature -> double
public static explicit operator double(Temperature temp)
{
return temp.Celsius;
}
}
class Program
{
static void Main()
{
Temperature temp = new Temperature(25.0);
// 显式转换:必须使用 (double)
double celsius = (double)temp;
Console.WriteLine(celsius); // 输出: 25.0
}
}
访问关键字
访问关键字用于访问对象或类的包含类或基类。
| 访问关键字 | |
|---|---|
| base | this |
base 基础
base 关键字在继承和多态编程中非常有用,能够帮助你显式地访问或调用基类的成员。
-
调用基类构造函数:使用
base关键字显式调用基类的构造函数。 -
访问基类的方法/属性/字段:当子类覆盖或隐藏基类的方法、属性或字段时,使用
base关键字可以访问基类的成员。 -
解决多态性中的冲突:在多态性场景中,
base可以用于访问基类版本的成员,即使子类已覆盖了这些成员。
// 调用基类的构造函数
class Animal
{
public Animal(string name)
{
Console.WriteLine($"Animal: {name}");
}
}
class Dog : Animal
{
public Dog(string name) : base(name) // 调用基类的构造函数
{
Console.WriteLine("Dog constructor.");
}
}
// 访问基类的方法/属性/字段
class Animal
{
public void Speak()
{
Console.WriteLine("Animal speaks");
}
}
class Dog : Animal
{
public new void Speak() // 使用 `new` 重写基类的方法
{
Console.WriteLine("Dog barks");
}
public void CallBaseSpeak()
{
base.Speak(); // 使用 `base` 调用基类的 `Speak` 方法
}
}
this 关键字的作用
-
**引用当前对象的实例:**当你需要在一个方法、属性或构造函数中引用当前类的实例时,可以使用
this。这在处理具有与字段同名的参数的方法时特别有用。public class Person { private string name; public Person(string name) { this.name = name; // 使用this来区分成员变量和参数 } } -
传递当前对象作为参数:可以在调用其他方法时将当前对象作为一个参数传递给该方法。
public void PrintInfo() { Console.WriteLine($"Name: {name}"); } public void IntroduceYourself() { Greet(this); // 将当前对象传给Greet方法 } public void Greet(Person person) { Console.WriteLine($"Hello, I am {person.name}."); } -
用于索引器:在定义索引器时,
this用来表示这个类的对象可以像数组那样被索引。public class MyCollection { private int[] items = new int[100]; public int this[int index] { get { return items[index]; } set { items[index] = value; } } } -
链式构造函数调用:在构造函数内部,
this也可以用来调用同一个类中的另一个构造函数。这种机制叫做构造函数链。public class Person { public string FirstName { get; set; } public string LastName { get; set; } public Person() : this("Unknown", "Unknown") // 调用带有两个参数的构造函数 { } public Person(string firstName, string lastName) { FirstName = firstName; LastName = lastName; } } -
**扩展静态类方法:**扩展方法的核心三要素是静态类,静态方法,和this参数。既在静态类中定义的静态方法,该方法的第一个参数带
this。public class Program { static void Main(string[] args) { string name = "233"; // 字符串可以直接使用 扩展的静态方法 TestString() name.TestString(); int age = 3; age.TestInt(); Console.ReadKey(); } } public static class Espandi { public static void TestString(this string s) { Console.WriteLine("这是 string 的扩展方法:" + s); } public static void TestInt(this int t) { Console.WriteLine("这是 int 的扩展方法:" + t); } }
字面量关键字
字面量关键字适用于对象的当前实例或值。
| 字面量关键字 | ||||
|---|---|---|---|---|
| null | false | true | value | void |
类型关键字
类型关键字用于数据类型。
| 输入关键字 | ||||||||
|---|---|---|---|---|---|---|---|---|
| bool | byte | char | class | decimal | double | enum | float | int |
| sbyte | short | string | struct | uint | ulong | ushort | long |
enum 枚举
枚举是一组命名整型常量。枚举类型是使用 enum 关键字声明的。
C# 枚举是值类型。换句话说,枚举包含自己的值,且不能继承或传递继承。
枚举的声明如下
访问修饰符 enum 枚举名:基础类型
{
用逗号分隔的标识符列表
}
Tips: 枚举列表中的每个符号代表一个整数值,一个比它前面的符号大的整数值。默认情况下,第一个枚举符号的值是 0,往后的值如果未定义将自动比前一个值大 1
示例一
using System;
public class EnumTest
{
enum Day { Sun, Mon, Tue, Wed, Thu, Fri, Sat };
static void Main()
{
int x = (int)Day.Sun;
int y = (int)Day.Fri;
Console.WriteLine("Sun = {0}", x);
Console.WriteLine("Fri = {0}", y);
}
}
结果:
Sun = 0
Fri = 5
示例二
using System;
public class EnumTest
{
public enum Number:uint
{
a = 1,
b = 2,
c,
d = 1,
e
}
public void Mian()
{
int a = (int)Number.a;
int c = (int)Number.c;
int e = (int)Number.e;
Console.WriteLine("a = {0}", a);
Console.WriteLine("c = {0}", c);
Console.WriteLine("e = {0}", e);
}
}
结果:
a = 1
c = 3
e = 2
Tips: enum 类型都是继承 System.Enum,但是 System.Enum 本身不是枚举类型,相反,它是一个类类型,所有枚举类型都是从它派生的。
struct 结构体
在 C# 中,结构体是值类型数据结构。它使得一个单一变量可以存储各种数据类型的相关数据。struct 关键字用于创建结构体。
结构体的声明如下
访问修饰符 struct 结构体名
{
多个成员的数据类型
}
Tips: 结构体字段必须是静态的 (static) 才能直接初始化,不然不能初始化。结构体不能声明默认的构造函数(不带参数的)或析构函数。在结构体进行赋值的时候,将结构赋值给新的变量时,将复制所有的数据,并且对新副本进行的任何修改将不会修改原始副本的值。
C# 结构的特点
- 结构可带有方法、字段、索引、属性、运算符方法和事件。
- 结构可定义构造函数,但不能定义析构函数。但是,您不能为结构定义无参构造函数。无参构造函数(默认)是自动定义的,且不能被改变。
- 与类不同,结构不能继承其他的结构或类。
- 结构不能作为其他结构或类的基础结构。
- 结构可实现一个或多个接口。
- 结构成员不能指定为 abstract、virtual 或 protected。
- 当您使用 New 操作符创建一个结构对象时,会调用适当的构造函数来创建结构。与类不同,结构可以不使用 New 操作符即可被实例化。
- 如果不使用 New 操作符,只有在所有的字段都被初始化之后,字段才被赋值,对象才被使用。
类和结构的区别:
- 类是引用类型,结构是值类型。
- 结构不支持继承。
- 结构不能声明默认的构造函数。
示例一
using System;
class StructTest
{
public struct Books
{
public string title;
public string author;
public string subject;
public int book_id;
}
public void Main()
{
Books Book1; /* 声明 Book1,类型为 Books */
Books Book2; /* 声明 Book2,类型为 Books */
/* book 1 详述 */
Book1.title = "C Programming";
Book1.author = "小明";
Book1.subject = "C Programming Tutorial";
Book1.book_id = 6495407;
/* book 2 详述 */
Book2.title = "Telecom Billing";
Book2.author = "小明";
Book2.subject = "Telecom Billing Tutorial";
Book2.book_id = 6495700;
/* 打印 Book1 信息 */
Console.WriteLine("Book 1 title : {0}", Book1.title);
Console.WriteLine("Book 1 author : {0}", Book1.author);
Console.WriteLine("Book 1 subject : {0}", Book1.subject);
Console.WriteLine("Book 1 book_id :{0}", Book1.book_id);
/* 打印 Book2 信息 */
Console.WriteLine("Book 2 title : {0}", Book2.title);
Console.WriteLine("Book 2 author : {0}", Book2.author);
Console.WriteLine("Book 2 subject : {0}", Book2.subject);
Console.WriteLine("Book 2 book_id : {0}", Book2.book_id);
}
}
结果:
Book 1 title : C Programming
Book 1 author : 小明
Book 1 subject : C Programming Tutorial
Book 1 book_id : 6495407
Book 2 title : Telecom Billing
Book 2 author : 小明
Book 2 subject : Telecom Billing Tutorial
Book 2 book_id : 6495700
示例二
using System;
class StructTest
{
public struct Books
{
public string title;
public string author;
public string subject;
public int book_id;
public void setValue(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 void Main()
{
Books book3 = new Books();
book3.setValue("C Programming", "Nuha Ali", "C Programming Tutorial", 6495407);
book3.display();
}
}
结果:
Title : C Programming
Author : Nuha Ali
Subject : C Programming Tutorial
Book_id : 6495407
内容相关关键字
上下文关键字仅在特定上下文中使用时才被视为关键字。它们不是保留的,因此可以用作名称或标识符。
| 内容相关关键字 | ||||||
|---|---|---|---|---|---|---|
| add | remove | var | dynamic | global | set | value |
当上下文关键字用作Visual Studio中的标识符时,不会将其转换为蓝色(Visual Studio中关键字的默认颜色)。
add 添加 remove 移除
add 是一个访问器关键字,通常用于事件的定义。它用于定义事件的添加方法,即当一个事件处理程序被注册时(例如通过 += 操作符),会调用此方法。add 关键字是隐式和显式定义事件时的一部分。
class MyEventPublisher
{
private event EventHandler myEvent;
// 自定义 'add' 访问器
public event EventHandler MyEvent
{
add
{
Console.WriteLine("Adding event handler...");
myEvent += value;
}
remove
{
Console.WriteLine("Removing event handler...");
myEvent -= value;
}
}
public void RaiseEvent()
{
myEvent?.Invoke(this, EventArgs.Empty);
}
}
class Program
{
static void Main()
{
MyEventPublisher publisher = new MyEventPublisher();
publisher.MyEvent += (sender, e) => Console.WriteLine("Event raised!");
publisher.RaiseEvent(); // 输出: Adding event handler... Event raised!
publisher.MyEvent -= (sender, e) => Console.WriteLine("Event raised!");
publisher.RaiseEvent(); // 输出: Removing event handler...
}
}
var 隐式变量
在 C# 中,变量必须使用数据类型声明。这些称为显式类型变量。
// 显示类型变量
int i = 100;
C# 3.0 引入了 var 关键字来声明方法级变量,而无需显式指定数据类型。
// 隐式类型的局部变量
var j = 100;
编译器将从 = 运算符右侧的表达式中推断出变量的类型。上面,var将编译为int。
var 可用于声明任何内置数据类型,用户定义类型或匿名类型变量。
Tips:
- 隐式类型的变量必须在声明时进行初始化;
- var 不允许在单个语句中多次声明变量。
- var 不能用于函数参数。
- var 可以在 for 和 foreach 循环中使用。
- var 也可以与LINQ查询一起使用。
dynamic 动态的
dynamic 关键字用于动态类型的声明。与静态类型不同,动态类型在编译时并不进行类型检查,类型的解析推迟到运行时。这意味着你可以在运行时决定对象的类型,并在运行时对其进行操作,而不需要在编译时指定类型。
-
当你使用
dynamic类型时,编译器不会检查该对象的成员是否存在或是否有效,这些检查会在运行时进行。 -
dynamic类型通常与反射、COM 互操作、动态语言等情况一起使用。
class Program
{
static void Main()
{
dynamic obj = 10; // obj 被动态地指定为 int 类型
Console.WriteLine(obj); // 输出: 10
obj = "Hello, world!"; // obj 现在是一个字符串
Console.WriteLine(obj); // 输出: Hello, world!
obj = new { Name = "Alice", Age = 30 }; // 动态匿名类型
Console.WriteLine(obj.Name); // 输出: Alice
}
}
查询关键词
查询关键字是LINQ查询中使用的上下文关键字。
| 查询关键词 | ||||||
|---|---|---|---|---|---|---|
| from | where | select | group | into | orderby | join |
| let | in | on | equals | by | ascending | descending |
详细可以去看这篇文章
C# LINQ 基础教程C# LINQ(语言集成查询)基础知识汇总,主要内容是LINQ的扩展方法合集。让我们一起查缺补漏 - 掘金
总结
如上所述,关键字不能用作标识符(变量名,类,接口等)。但是,它们可以与前缀“ @”一起使用。例如,该类是保留关键字,因此它不能用作标识符,但可以按如下所示使用@class。
要记住的要点:
- 关键字是保留字,不能用作名称或标识符。
- 如果要使用关键字作为标识符,请在关键字前面加上“@”。
- C# 包括各种类别的关键字,例如修饰符关键字,访问修饰符关键字,语句关键字,方法参数关键字等。
- 上下文关键字可以用作标识符。