.NET体系结构

主要内容包括:

C#与.NET的关系、公共语言运行库、中间语言、程序集、.NET Framework类、名称空间、内层管理...

C#与.NET的关系

C#是门高级编程语言,.NET(Framework)是个环境,用C#编写的所有代码总是在.NET Framework中运行。

CLR公共语言运行库

 它是.NET Framework的核心,在CLR控制下运行的代码称为托管代码。CLR执行编写好的源代码之前,需要编译它。

编译分两个阶段:

1)将源代码编译为Microsoft中间语言(IL)

2)CLR把IL编译为平台专用代码。

这种设计的重要优点:

1)平台无关性,依托的是:CTS是通用类型系统,CLS是通用语言规范,

2)提高性能

3)语言的互操作性,COM、windows运行库

中间语言

应用程序域

就是为安全性,可靠性,隔离性,和版本控制,及卸载程序提供的隔离边界。它通常由运行库宿主创建,应用程序域提供了一个更安全,用途更广的处理单元。

程序集

程序集是.NET时代的动态链接库DLL,程序集是包含编译好的、面向.NET Framework的代码的逻辑单元。

程序集包括(中间语言(IL),元数据(metaData),资源(resource),装配清单(AL))。

它包含的元数据(描述自身的数据)描述了对应代码中定义的类型和方法。

可以编程访问这些元数据,这个技术称为“反射”。抽象工厂设计模式中有用到:

static string AssemblyName = Assembly.GetExecutingAssembly().GetName().Name; //获取程序集名称
string className = AssemblyName+".Models" + "." + db + "User";   //命名空间.类名称
(IUser)Assembly.Load(AssemblyName).CreateInstance(className);    //获取IUser程序集

可执行代码和库代码,使用相同的程序集结构,他们的区别是:

可执行代码的程序集包含一个主程序的入口点,而库程序集不包含。

.NET Framework类

属于托管类,使用托管代码的好处是可以使用.NET基类库,非常多的类的集合。大部分.net基类库是用C#写的。

名称(命名)空间

是.NET避免类名冲突的一种方式。

Microsoft建议都至少要提供两个嵌套的命名空间名,第一个是公司名,第二个是技术名称或者软件包的名称,再之后是类名。

内存管理

1、GC(Garbage collector)

GC是垃圾收集器。CLR通过GC实现的自动内存管理。

1)什么被认为是可回收的对象?
GC采用一定的算法遍历所有的对象,找出可达对象和不可达对象,不可达对象是可回收的对象。
2)什么时候回收?
通常情况下:内存不足溢出时,确切的说,是第一代对象已满的时候。
3)如何回收?
垃圾收集进程来释放不可达对象的内存空间。
4)回收完后,还需要做什么?
避免托管堆上的内存碎片,重新分配内存,压缩托管堆。
5)避免垃圾回收带来的性能影响,采用代龄机制。

如要请求垃圾收集,可以调用下面的方法之一: 
System.gc()
Runtime.getRuntime().gc()

2、托管资源vs非托管资源

资源就是程序中可利用的数据,譬如:字符串、图片和任何二进制数据,包括任何类型的文件。

托管资源是由CLR全权负责的资源,CLR不负责的资源为非托管资源。
对于托管资源通过GC自动清理回收。对于非托管资源,通过代码调用手动进行清除,再由GC回收
如何正确的释放资源:对于非托管的资源,一般就是,Stream(流),数据库的连接,网络连接等的这些操作系统资源,需要我们手动去释放。

Net提供了三种释放方法:Dispose,Close,析构函数(也就是Finalize方法)

3、 托管内存与非托管内存之间的转换

c#有自己的内存回收机制,所以在c#中我们可以只new,不用关心怎样delete,c#使用gc来清理内存,这部分内存就是managed memory,大部分时候我们工作于c#环境中,都是在使用托管内存,然而c#毕竟运行在c++之上,有的时候,(比如可能我们需要引入一些第三方的c++或native代码的库,在Unity3d开发中很常见)我们需要直接在c#中操纵非托管的代码,这些non-managed memory我们就需要自己去处理他们的申请和释放了, c# 中提供了一些接口,完成托管和非托管之间的转换,以及对这部分内存的操作。

主要通过Marshal类和GCHandle类,编程时只要注意非托管的内存一定要负责好释放就可以了。

例如:Marshal.AllocHGlobal()

public static IntPtr AllocHGlobal(
    int cb  //内存中的所需字节数。
)
通过使用指定的字节数,从进程的非托管内存中分配内存。
返回值:指向新分配的内存的指针。 必须使用释放此内存 Marshal.FreeHGlobal 方法。
public static void FreeHGlobal(
    IntPtr hglobal
)
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(cardCfg));
Marshal.StructureToPtr(cardCfg, ptr, false);

InrPtr是个结构体:用于表示指针或句柄的平台特定类型。
FreeHGlobal()用法
//byte[]转换为Intptr
  public static Intptr BytesToIntptr(byte[] bytes)
  {
    int size = bytes.Length;
    IntPtr buffer = Marshal.AllocHGlobal(size);
    try
      {
       Marshal.Copy(bytes, 0, buffer, size);
       return buffer;
      }
    finally
      {
       Marshal.FreeHGlobal(buffer); //释放以前从进程的非托管内存中分配的内存。
      }
  }
View Code
原文地址:https://www.cnblogs.com/peterYong/p/6556749.html