C# 关键字总结




const和readonly

https://www.cnblogs.com/aehyok/p/3529079.html

静态常量:是指编译器在编译时候会对常量进行解析,并将常量的值替换成初始化的那个值。

动态常量的值则是在运行的那一刻才获得的,编译器编译期间将其标示为只读常量,而不用常量的值代替,这样动态常量不必在声明的时候就初始化,而可以延迟到构造函数中初始化。

  1. const是静态常量。
    readonly是动态常量。
  2. const修饰的常量在声明的时候必须初始化。
    readonly修饰的常量则可以延迟到构造函数初始化
  3. const修饰的常量在编译期间就被解析,即常量值被替换成初始化的值
    readonly修饰的常量则延迟到运行的时候
  4. const修饰的常量注重的是效率
    readonly修饰的常量注重灵活
  5. const修饰的常量没有内存消耗
    readonly因为需要保存常量,所以有内存消耗
  6. const只能修饰基元类型、枚举类、或者字符串类型
    readonly没有这个限制

this

用法1:this代表当前类实例对象

public class Animal
{
    private string name;

    public void SetName(string name)
    {
        this.name = name;
    }
}

用法2:this串联构造函数
this指向本实例的构造函数。表示在执行本构造函数之前,先执行this指向的本实例的构造函数,再执行本函数。

public class Animal
{
    private string name;
    public string Name { get { return name; } }

    public Animal(string name)
    {
        this.name = name;
        Console.WriteLine("执行有参构造函数");
    }

    /// <summary>
    /// 可以保证先执行带参的构造函数
    /// </summary>
    public Animal() : this("default")
    {
        Console.WriteLine("执行无参构造函数");
    }
}

class Program
{
    static void Main(string[] args)
    {
        Animal animal = new Animal();
		//输出default
		//保证了即使我们调用空构造函数,也会给name赋初值
        Console.WriteLine(animal.Name);
    }
}

用法3:this做索引器

public class Animal
{
    public float HandLength { get; set; }
    public float LegLength { get; set; }
    public float HairLength { get; set; }

    public float this[int index]
    {
        get
        {
            switch (index)
            {
                case 0:
                    return this.HandLength;
                case 1:
                    return this.LegLength;
                case 2:
                    return this.HairLength;
                default:
                    //数组越界异常
                    throw new ArgumentOutOfRangeException();
            }
        }
        set
        {
            switch (index)
            {
                case 0:
                    this.HandLength = value;
                    break;
                case 1:
                    this.LegLength = value;
                    break;
                case 2:
                    this.HairLength = value;
                    break;
                default:
                    //数组越界异常
                    throw new ArgumentOutOfRangeException();
            }
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        Animal animal = new Animal();

        //Set
        animal[0] = 70;
        animal[1] = 100;
        animal[2] = 12;

        //Get
        Console.WriteLine("手长:{0},腿长:{1},头发长:{2}", animal[0], animal[1], animal[2]);
    }
}

ref和out

  1. ref和out都通过引用来传递参数。
  2. 使用ref时,必须在传入前初始化。
    使用out时,传入前不用初始化但必须再传入方法里初始化。
    private static void Method1(out int num)
    {
        num = 10;
    }
    private static void Method2(ref int num)
    {
        num = 20;
    }

    static void Main(string[] args)
    {
        int num1;
        Method1(out num1);

        int num2 = 1;
        Method2(ref num2);
    }

sealed

  1. 当类声明sealed时,可以防止其他类继承此类。
  2. 当方法或属性声明sealed时(要和override一起使用),可以防止子类重写。
public class Animal { }
//任何类都不能继承Dog类
public sealed class Dog : Animal { }
public class Animal
{
    protected virtual void Method() { }
}

public class Dog : Animal
{
    //sealed必须和override一起使用
    protected sealed override void Method()
    {
    }
}
//C类则无法再对Method进行重写
public class GoldHair : Dog{ }

out和in,协变和逆变

https://www.cnblogs.com/qixuejia/p/4383068.html

要把泛型类型参数定义为协变,用out关键字,协变类型只能用做方法的返回值或属性get访问器。

要把泛型类型参数定义为逆变,用in关键字,逆变类型只能用做方法参数,不能用做返回类型

internal

  1. 用于类型或成员,使用该修饰符声明的类型或成员只能在同度一程集内访问。(就是只能在同一个项目中使用)

  2. 接口的成员不能使用internal修饰符。

implicit和explicit

https://www.jb51.net/article/161716.htm

  1. 在常用的类型转换时,经常会遇到隐式、显示转换。
    当我们需要隐式、显示转换自定义的类型时,就用到了这俩修饰符。

  2. implicit用于隐式转换。
    使用后,在编译时会跳过异常检查,所以隐式转换运算符应当从不引发异常并且从不丢失信息,否则在运行时可能会出问题。

public class Animal
{
    private string name;
    public string Name { get { return name; } }

    public Animal(string name)
    {
        this.name = name;
    }

    /// <summary>
    /// 隐式转换。从Animal到string
    /// </summary>
    public static implicit operator string(Animal animal)
    {
        return animal.name;
    }

    /// <summary>
    /// 隐式转换。从string到Animal
    /// </summary>
    public static implicit operator Animal(string name)
    {
        return new Animal(name);
    }
}

class Program
{
    static void Main(string[] args)
    {
        Animal animal1 = new Animal("Ffly");

        //隐式转换
        string name = animal1;
        Animal animal2 = "Fflyqaq";

        Console.WriteLine("name = {0} animal2 = {1}", name, animal2.Name);
    }
}
  1. explicit用于显示转换。
public class Animal
{
    private string name;
    public string Name { get { return name; } }

    public Animal(string name)
    {
        this.name = name;
    }

    /// <summary>
    /// 显示转换。从Animal到Plant
    /// </summary>
    public static explicit operator Plant(Animal animal)
    {
        return new Plant(animal.name);
    }
}

public class Plant
{
    private string name;
    public string Name { get { return name; } }

    public Plant(string name)
    {
        this.name = name;
    }
}

class Program
{
    static void Main(string[] args)
    {
        Animal animal = new Animal("Ffly");

        Plant plant = (Plant)animal;
    }
}

extern

https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/keywords/extern

extern 修饰符用于声明在外部实现的方法。
extern 修饰符的常见用法是在使用 Interop 服务调入非托管代码时与 DllImport 特性一起使用。在这种情况下,必须将方法声明为static。

原文地址:https://www.cnblogs.com/Fflyqaq/p/12893744.html