C# 关键字

562 阅读18分钟

修饰词关键字

修饰词关键字是特定的关键字,指示谁可以修改类型和类型成员。修饰符允许或阻止程序的某些部分被其他部分修改。

修饰词关键字
abstractasyncconsteventexternnewoverride
sealedstaticunsafevirtualvolatilereadonlypartial

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 来隐藏基类中具有相同名称的成员(例如方法、属性、字段等)。这与 virtualoverride 不同,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关键字。

访问修饰符关键字

访问修饰符应用于类,方法,属性,字段和其他成员的声明。它们定义了类及其成员的可访问性。

访问修饰符
publicprivateinternalprotectedprotected internal

public 公共的

public 公有访问,不受任何限制。

private 私有的

private 私有访问,只限于本类成员访问,子类、实例都不能访问。

internal 内部的

internal 内部访问,只限于本项目内访问,其他不能访问。

Tips:如果没有指定修饰符,这是默认访问修饰。

protected 受保护的

protected 保护访问,只限于本类和子类访问,实例不能访问。

protected internal 受保护的内部成员

protected internal 内部保护访问,只限于本项目或者子类访问,其他不能访问。

语句关键字

语句关键字
条件语句ifelseelse ifswitchcase
循环控制forforeachwhiledoyield
跳转控制breakcontinuegotoreturnthrow
异常处理trycatchfinally
异步编程asyncawait
资源管理usinglock

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)
    {
        // 只有一个线程能进入此代码块
    }
}

方法参数关键字

方法参数关键字
refoutinparamsthis

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
    }
}

命名空间关键字

这些关键字与名称空间和相关运算符一起应用。

命名空间关键字
usingextern aliasnamespace

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
{

}

运算符关键字

运算符关键字执行其他操作。

运算符关键词
asoperatorissizeoftypeof
stackalloccheckeduncheckedimplicitexplicit

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
    }
}

访问关键字

访问关键字用于访问对象或类的包含类或基类。

访问关键字
basethis

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 关键字的作用

  1. **引用当前对象的实例:**当你需要在一个方法、属性或构造函数中引用当前类的实例时,可以使用 this。这在处理具有与字段同名的参数的方法时特别有用。

    public class Person
    {
        private string name;
    
        public Person(string name)
        {
            this.name = name; // 使用this来区分成员变量和参数
        }
    }
    
  2. 传递当前对象作为参数:可以在调用其他方法时将当前对象作为一个参数传递给该方法。

    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}.");
    }
    
  3. 用于索引器:在定义索引器时,this 用来表示这个类的对象可以像数组那样被索引。

    public class MyCollection
    {
        private int[] items = new int[100];
    
        public int this[int index]
        {
            get { return items[index]; }
            set { items[index] = value; }
        }
    }
    
  4. 链式构造函数调用:在构造函数内部,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;
        }
    }
    
  5. **扩展静态类方法:**扩展方法的核心三要素是静态类,静态方法,和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);
        }
    }
    

字面量关键字

字面量关键字适用于对象的当前实例或值。

字面量关键字
nullfalsetruevaluevoid

类型关键字

类型关键字用于数据类型。

输入关键字
boolbytecharclassdecimaldoubleenumfloatint
sbyteshortstringstructuintulongushortlong

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

内容相关关键字

上下文关键字仅在特定上下文中使用时才被视为关键字。它们不是保留的,因此可以用作名称或标识符。

内容相关关键字
addremovevardynamicglobalsetvalue

当上下文关键字用作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查询中使用的上下文关键字。

查询关键词
fromwhereselectgroupintoorderbyjoin
letinonequalsbyascendingdescending

详细可以去看这篇文章

C# LINQ 基础教程C# LINQ(语言集成查询)基础知识汇总,主要内容是LINQ的扩展方法合集。让我们一起查缺补漏 - 掘金

总结

如上所述,关键字不能用作标识符(变量名,类,接口等)。但是,它们可以与前缀“ @”一起使用。例如,该类是保留关键字,因此它不能用作标识符,但可以按如下所示使用@class。

要记住的要点:

  1. 关键字是保留字,不能用作名称或标识符。
  2. 如果要使用关键字作为标识符,请在关键字前面加上“@”。
  3. C# 包括各种类别的关键字,例如修饰符关键字,访问修饰符关键字,语句关键字,方法参数关键字等。
  4. 上下文关键字可以用作标识符。