c# 基础知识记录

关于using
using Student = System.Student
 
extern alias 外部别名
 
类型对象,定义一个类,就会生成一个类型对象。如果对象引用了这个类的实例,CLR会保证先把类的类型对象加载到堆上面去
 
类型对象上面有什么?
类型对象指针、同步块索引、静态字段
一张方法表,类上面自己定义的方法
 
构造一个类的实例,会在堆上面构造好,实例也有类型对象指针、同步块索引,CLR把实例的的类型对象指针指向了类型对象
注意类的最基类的类型对象,类型对象指针,都会指向Type的类型对象上面去,Type类型对象的类型对象指针指向自己
同时在栈上面,会有一个变量指向着堆上构造好的这个实例
 
调用实例方法或者类的静态方法,第一件事都是先找到这个类的类型对象,然后才是在类型对象的方法表里,找方法
有可能方法是从基类继承过来的,所以需要顺着基类的类型对象接着找
 
日常写法
int a = 0;
 
实际的写法
System.Int32 a = new System.Int32(); // 还是要构造实例
之所以能用int,可以想象成,打头的位置,有一句
using int = System.Int32;
 
byte b = 100;
// 发生溢出
b = (byte)(b+200);
// 溢出检查,注意可以在工程文件上配置,检查溢出
b = checked((byte)(b + 200));
// 或者
checked {
// ...
}
 
类型也分成值类型、引用类型
值类型也是类,构造时也会构造出来一个实例,但是注意,值类型的实例不是存储在堆上的,而是在栈上面,也不在CLR垃圾回收的范围,值类型的实例被回收时,不会调用类上面的 Finalize方法
 
Object->ValueType->值类型/Enum枚举类型
如果一个引用类型中,有几个值类型的成员,那么引用类型的实例部分,将全部分配到堆上头去
值类型复制时,要构造一个实例,把老的实例的所有东西都复制一份,然后新的实例依然分配在栈上面
堆类型复制时,仅仅拷贝实例的地址,赋值给栈的一块变量
 
c#代码里头出现的object类型,特指的是已经排除了值类型之外的类,其实就是引用类型
值类型和引用类型的机制不一样,因此从值类型赋值给引用类型,必须转换,也就是装箱
  • 装箱其实就是在堆上面,分配一个对象,增加了必须的两个字段,类型对象指针,同步块索引,然后把那些值都拷贝过去,返回对象地址
  • 当把一个对象赋值给一个值类型变量时,就需要拆箱,拆箱就是找到堆上头的那个实例的地址,如果拆箱完了是赋值给一个变量的话,那么紧接着就把堆上面的对象的数据,挨个儿赋值给栈上头的那个值类型实例
 
为了提升性能,减少不必要的装箱和拆箱,.net在ArrayList的基础上,提供了泛型List,另外扩展了Console.WriteLine的参数类型
不单单是传string类型,还有int double等等,这样可以避免装箱
而我们开发人员也应该注意,避免潜在的装箱和拆箱,例如:
int a = 3;
Console.WriteLine("result"+a); // 注意,String的Concat方法要求参数必须是object,这里的a先得装箱成object,才能进一步调用
// 可以替换成
Console.WriteLine("result"+a.ToString());
 
除了上面举的例子,明显两个东西类型不一样,涉及到了装箱和拆箱,还有一些应用场景,也会导致装箱和拆箱
  • 调用结构体的ToString方法,如果此方法是Object派生的方法,就需要装箱,否则结构体自己重写的不需要
  • 将结构体赋值给一个接口类型,结构体实现了这个接口,由于接口全部被定义成引用类型,因此需要装箱
  • 调用Object上面的GetType需要装箱
 
 
gcText1.Text = "1行目、" & vbCrLf & "2行目、" & vbCrLf & "3行目"
注意一下 VB 的写法
 
泛型相关
 
public class UsingEnum where T : System.Enum { } public class UsingDelegate where T : System.Delegate { } public class Multicaster where T : System.MulticastDelegate { }
 
class MyClass<t, u=""> where T : class where U : struct {
// ...
}
 
The new() Constraint lets the compiler know that any type argument supplied must have an accessible parameterless constructor
public class MyGenericClass where T : IComparable, new() { // The following line is not possible without new() constraint: T item = new T(); }
 
注意一下 .net framework 4.8编译出来的dll,可以用.net framework 4.7.2的工程引用。但是编译会报错,VS却没有任何智能提示
只能看到在 output下面输出编译有错误,代码却没有红线
posted @ 2022-07-03 18:20  内心澎湃的水晶侠  阅读(25)  评论(0编辑  收藏  举报