const和readonly
https://www.cnblogs.com/aehyok/p/3529079.html
静态常量:是指编译器在编译时候会对常量进行解析,并将常量的值替换成初始化的那个值。
动态常量的值则是在运行的那一刻才获得的,编译器编译期间将其标示为只读常量,而不用常量的值代替,这样动态常量不必在声明的时候就初始化,而可以延迟到构造函数中初始化。
- const是静态常量。
readonly是动态常量。 - const修饰的常量在声明的时候必须初始化。
readonly修饰的常量则可以延迟到构造函数初始化 - const修饰的常量在编译期间就被解析,即常量值被替换成初始化的值
readonly修饰的常量则延迟到运行的时候 - const修饰的常量注重的是效率
readonly修饰的常量注重灵活 - const修饰的常量没有内存消耗
readonly因为需要保存常量,所以有内存消耗 - 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
- ref和out都通过引用来传递参数。
- 使用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
- 当类声明sealed时,可以防止其他类继承此类。
- 当方法或属性声明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
-
用于类型或成员,使用该修饰符声明的类型或成员只能在同度一程集内访问。(就是只能在同一个项目中使用)
-
接口的成员不能使用internal修饰符。
implicit和explicit
https://www.jb51.net/article/161716.htm
-
在常用的类型转换时,经常会遇到隐式、显示转换。
当我们需要隐式、显示转换自定义的类型时,就用到了这俩修饰符。 -
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);
}
}
- 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。