值类型:值类型的实例一般在线程的栈上分配

引用类型:引用类型的实例在线程的托管堆上分配

引用类型变量的Equals比较的是二者的引用地址而不是内部的值,值类型变量的Equals方法比较的是二者的值。

堆栈与托管堆

线程堆栈(Thread Stack):先进后出 (Last-In/First-Out)

堆栈中存储值类型。

堆栈实际上是向下填充,即由高内存地址指向地内存地址填充。

堆栈的工作方式是先分配内存的变量后释放(先进后出原则)。

堆栈中的变量是从下向上释放,这样就保证了堆栈中先进后出的规则不与变量的生命周期起冲突!

堆栈的性能非常高,但是对于所有的变量来说还不太灵活,而且变量的生命周期必须嵌套。

通常我们希望使用一种方法分配内存来存储数据,并且方法退出后很长一段时间内数据仍然可以使用。此时就要用到堆(托管堆)!

托管堆(Managed Heap):托管堆分配在被操作系统保留的一段内存区域中,这段内存区域是由CLR来管理的,这段内存称之为托管堆。

堆(托管堆)存储引用类型。

此堆非彼堆,.NET中的堆由垃圾收集器自动管理。

与堆栈不同,堆是从下往上分配,所以自由的空间都在已用空间的上面。

每个正在运行的程序都对应着一个进程(process),在一个进程内部,可以有一个或多个线程(thread),每个线程都拥有一块“自留地”,称为“线程堆栈”,大小为1M,用于保存自身的一些数据,比如函数中定义的局部变量、函数调用时传送的参数值等,这部分内存区域的分配与回收不需要程序员干涉。所有值类型的变量都是在线程堆栈中分配的。读取速度快。

另一块内存区域称为“堆(heap)”,在.NET 这种托管环境下,堆由CLR 进行管理,所以又称为“托管堆(managed heap)”。CLR的垃圾回收机制负责定期清理。读取速度慢。

堆栈和堆(托管堆)都在进程的虚拟内存中。(在32位处理器上每个进程的虚拟内存为4GB,64位Windows的虚拟内存为16 TB)

虚拟内存(VirtualMemory)是Windows管理所有可用内存的方式。对于32位Windows系统,每个进程所用到的虚拟内存地址从0到2^32-1,总容量4GB,其中2GB是与操作系统以及其他所有进程所共享,另外2GB分派给进程独占(这就是常说的32位Windows中一个进程最多能用2G内存的由来)。

进程:是操作系统结构的基础;是一个正在执行的程序;

线程:有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。

线程与进程的区别可以归纳为以下4点:

1)地址空间和其它资源(如打开文件):进程间相互独立,同一进程的各线程间共享。某进程内的线程在其它进程不可见。

2)通信:进程间通信IPC,线程间可以直接读写进程数据段(如全局变量)来进行通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。

3)调度和切换:线程上下文切换比进程上下文切换要快得多。

4)在多线程OS中,进程不是一个可执行的实体。

线程安全: 如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。

 

类型安全:类型安全应该算是CLR最重要的特性之一了,在运行时,CLR总是知道一个对象的类型。在C#中可以调用GetType()来返回调用对象的类型,并且由于GetType()继承于System.Object对象,并且为非虚的方法,所以一个类型不可能通过重写此方法而伪装成另一种类型。C++不是类型安全的,因为两个不同类型的指针之间可以强制转换。

 

is的规则如下:检查对象类型的兼容性,并返回结果,true或者false;不会抛出异常;如果对象为null,则返回值永远为false。

as的规则如下:检查对象类型的兼容性,并返回结果,如果不兼容就返回null;不会抛出异常; 如果结果判断为空,则强制执行类型转换将抛出NullReferenceException异常。

null在.NET中,null表示一个对象引用是无效的。

Nullable<T>(可空类型)

       int? i = null;
         Nullable<int> i = null;

Nullable本质上仍是一个struct为值类型,其实例对象仍然分配在线程栈上。其中的value属性封装了具体的值类型,Nullable<T>进行初始化时,将值类型赋给value

  • 可空类型表示值为null的值类型。
  • 不允许使用嵌套的可空类型,例如Nullable<Nullable<T>> 。
  • Nullable<T>和T?是等效的。
  • 对可空类型执行GetType方法,将返回类型T,而不是Nullable<T>。
  • c#允许在可空类型上执行转换和转型,例如:

int? a = 100;

Int32 b = (Int32)a;

a = null;

  • 同时为了更好的将可空类型于原有的类型系统进行兼容,CLR提供了对可空类型装箱和拆箱的支持。

泛型:泛型(generic)是CLR和编程语言提供的一种特殊机制,它支持一种形式的代码重用,即“算法重用”。

1.性能高:定义数据类型,不需要类型转换,避免拆装箱带来的性能损失;
2.类型安全:定义允许使用的数据类型,在编译时检查类型错误,及早发现错误。

概述:

  • 使用泛型类型可以最大限度地重用代码、保护类型的安全以及提高性能。
  • 泛型最常见的用途是创建集合类。
  • .NET Framework 类库在 System.Collections.Generic 命名空间中包含几个新的泛型集合类。应尽可能地使用这些类来代替普通的类,如 System.Collections命名空间中的 ArrayList
  • 您可以创建自己的泛型接口、泛型类、泛型方法、泛型事件和泛型委托。
  • 可以对泛型类进行约束以访问特定数据类型的方法。
  • 关于泛型数据类型中使用的类型的信息可在运行时通过反射获取。

 

对象哈希码:

Equals的作用是比较对象实例是否相等。MSDN中提到,Object默认支持引用相等,如果想要判断值相等,就要重写Equals。判断两个实例是否是一个引用时,通常是通过object.ReferenceEquals(obj1,
obj2);

GetHashCode就是获取这个对象的实例唯一标示,当你重写Equals时,如果不重写GetHashCode,生成时就会有警告。

1. 不建议使用值类型对象的GetHashCode函数返回值来作为HashTable对象的Key;

2. 引用类型是可以使用的,但是要注意如果重写了Equals函数,一定要重写GetHashCode函数来达到一致;

再说说重写此函数时需要注意的。

1. 不管是值类型还是引用类型,要保证产生HashCode的成员不能被修改;

2. 对于产生HashCode的成员修改,要以产生新对象进行处理,同时要在使用端作相应的修改,即先删除旧的在添加新的。

使用类型的GetHashCode有微妙的危险,所以使用的时候要特别注意。

 

dynamic基元类型:

dynamic是FrameWork4.0的新特性。dynamic的出现让C#具有了弱语言类型的特性。编译器在编译的时候不再对类型进行检查,编译期默认dynamic对象支持你想要的任何特性。dynamic可以简化反射

 

大对象:在.Net 1.0和2.0中,如果一个对象的大小超过85000byte,就认为这是一个大对象。这个数字是根据性能优化的经验得到的。当一个对象申请内存大小达到这个阀值,它就会被分配到大对象堆上。大对象属于2代对象,因为只有GC在2代回收时才会处理大对象。

扩展方法(Extension Method):扩展方法是C# 3.0中新加入的特性。MSDN中对扩展方法的定义是:扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。

using在程序编译阶段,编译器会自动将using语句生成为try-finally语句,并在finally块中调用对象的Dispose方法,来清理资源。所以,using语句等效于try-finally语句

使用规则
    ①using只能用于实现了IDisposable接口的类型,禁止为不支持IDisposable接口的类型使用using语句,否则会出现编译错误
  ②using语句适用于清理单个非托管资源的情况,而多个非托管对象的清理最好以try-finnaly来实现,因为嵌套的using语句可能存在隐藏的Bug内层using块引发异常时,将不能释放外层using块的对象资源;
  ③using语句支持初始化多个变量,但前提是这些变量的类型必须相同,例如:
       
using(Pen p1 = new Pen(Brushes.Black), p2 = new Pen(Brushes.Blue))
     
{
         
//
     
}
    ④针对初始化对个不同类型的变量时,可以都声明为IDisposable类型,例如:
        using
(IDisposable font = new Font("Verdana", 12), pen = new
Pen(Brushes.Black))
     
{
         
float size = (font as Font).Size;
         
Brush brush = (pen as Pen).Brush;
     
}

 

Dictionary Hashtable的区别:

1:单线程程序中推荐使用 Dictionary, 有泛型优势, 且读取速度较快, 容量利用更充分。

2:多线程程序中推荐使用 Hashtable, 默认的 Hashtable 允许单线程写入, 多线程读取, 对 Hashtable
进一步调用 Synchronized() 方法可以获得完全线程安全的类型。 而Dictionary 非线程安全, 必须人为使用 lock 语句进行保护, 效率大减。

3:Dictionary 有按插入顺序排列数据的特性 (注: 但当调用 Remove() 删除过节点后顺序被打乱), 因此在需要体现顺序的情境中使用 Dictionary 能获得一定方便.

对于值类型,特定类型(不包括 Object)的 Dictionary<(Of <(TKey, TValue>)>) 的性能优于 Hashtable,这是因为 Hashtable 的元素属于 Object 类型,所以在存储或检索值类型时通常发生装箱和取消装箱操作。

垃圾回收(GC):GC如其名,就是垃圾收集。Garbage Collector(垃圾收集器)以应用程序的root为基础,遍历应用程序在Heap上动态分配的所有对象,通过识别它们是否被引用来确定哪些对象是已经死亡的、哪些仍需要被使用。已经不再被应用程序的root或者别的对象所引用的对象就是已经死亡的对象,即所谓的垃圾,需要被回收。这就是GC工作的原理。

  托管推分为3个代龄区域,相应的GC有3种方式: # Gen 0 collections, # Gen 1 collections, #Gen 2 collections。如果Gen 0 heap内存达到阀值,则触发0代GC,0代GC后Gen 0中幸存的对象进入Gen1。如果Gen 1的内存达到阀值,则进行1代GC,1代GC将Gen 0 heap和Gen 1 heap一起进行回收,幸存的对象进入Gen2。2代GC将Gen 0 heap、Gen 1 heap和Gen 2 heap一起回收,Gen 0和Gen 1比较小,这两个代龄加起来总是保持在16M左右;Gen2的大小由应用程序确定,可能达到几G,因此0代和1代GC的成本非常低,2代GC称为full GC,通常成本很高。粗略的计算0代和1代GC应当能在几毫秒到几十毫秒之间完成,Gen 2 heap比较大时,full GC可能需要花费几秒时间。大致上来讲.NET应用运行期间,2代、1代和0代GC的频率应当大致为1:10:100。

首先,GC并不是能释放所有的资源。它不能自动释放非托管资源。

第二,GC并不是实时性的,这将会造成系统性能上的瓶颈和不确定性。

C#线程同步的几种方法参见:http://www.cnblogs.com/michaelxu/archive/2008/09/20/1293716.html

c#.net基础的更多相关文章

  1. java基础集合经典训练题

    第一题:要求产生10个随机的字符串,每一个字符串互相不重复,每一个字符串中组成的字符(a-zA-Z0-9)也不相同,每个字符串长度为10; 分析:*1.看到这个题目,或许你脑海中会想到很多方法,比如判 ...

  2. node-webkit 环境搭建与基础demo

    首先去github上面下载(地址),具体更具自己的系统,我的是windows,这里只给出windows的做法 下载windows x64版本 下载之后解压,得到以下东西 为了方便,我们直接在这个目录中 ...

  3. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  4. Golang, 以17个简短代码片段,切底弄懂 channel 基础

    (原创出处为本博客:http://www.cnblogs.com/linguanh/) 前序: 因为打算自己搞个基于Golang的IM服务器,所以复习了下之前一直没怎么使用的协程.管道等高并发编程知识 ...

  5. [C#] C# 基础回顾 - 匿名方法

    C# 基础回顾 - 匿名方法 目录 简介 匿名方法的参数使用范围 委托示例 简介 在 C# 2.0 之前的版本中,我们创建委托的唯一形式 -- 命名方法. 而 C# 2.0 -- 引进了匿名方法,在 ...

  6. HTTPS 互联网世界的安全基础

    近一年公司在努力推进全站的 HTTPS 化,作为负责应用系统的我们,在配合这个趋势的过程中,顺便也就想去搞清楚 HTTP 后面的这个 S 到底是个什么含义?有什么作用?带来了哪些影响?毕竟以前也就只是 ...

  7. Swift与C#的基础语法比较

    背景: 这两天不小心看了一下Swift的基础语法,感觉既然看了,还是写一下笔记,留个痕迹~ 总体而言,感觉Swift是一种前后端多种语言混合的产物~~~ 做为一名.NET阵营人士,少少多多总喜欢通过对 ...

  8. .NetCore MVC中的路由(1)路由配置基础

    .NetCore MVC中的路由(1)路由配置基础 0x00 路由在MVC中起到的作用 前段时间一直忙于别的事情,终于搞定了继续学习.NetCore.这次学习的主题是MVC中的路由.路由是所有MVC框 ...

  9. .NET基础拾遗(5)多线程开发基础

    Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理基础 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开 ...

  10. .NET 基础 一步步 一幕幕[面向对象之方法、方法的重载、方法的重写、方法的递归]

    方法.方法的重载.方法的重写.方法的递归 方法: 将一堆代码进行重用的一种机制. 语法: [访问修饰符] 返回类型 <方法名>(参数列表){ 方法主体: } 返回值类型:如果不需要写返回值 ...

随机推荐

  1. PHP Math 函数 mt_rand() 使用 Mersenne Twister 算法返回随机整数。

    语法 mt_rand(min,max) 说明 如果没有提供可选参数 min 和 max,mt_rand() 返回 0 到 RAND_MAX 之间的伪随机数.例如想要 5 到 15(包括 5 和 15) ...

  2. JavaScript简易教程

    这是我所知道的最完整最简洁的JavaScript基础教程. 这篇文章带你尽快走进JavaScript的世界——前提是你有一些编程经验的话.本文试图描述这门语言的最小子集.我给这个子集起名叫做“Java ...

  3. 解决CSS图片底部3像素问题总结

    解决三像素问题的总结: 1.img标签的父标签增加font-size:0; 如.body{ font-size: 0; } 2.img标签增加display:block; img{display:bl ...

  4. asp.net通过distinct过滤集合(list)中重复项的办法

    /// <summary> /// 权限Distinct比较器 /// </summary> public class PermissionIdComparer : IEqua ...

  5. python:函数中五花八门的参数形式(茴香豆的『回』字有四种写法)

    毫不夸张的说,python语言中关于函数参数的使用,是我见过最为灵活的,随便怎么玩都可以,本文以数学乘法为例,演示几种不同的传参形式: 一.默认参数 def multiply1(x, y): retu ...

  6. Python开源框架、库、软件和资源大集合

    A curated list of awesome Python frameworks, libraries, software and resources. Inspired by awesome- ...

  7. [Go] 开发 go web 项目,踩到的一些“坑”

    注意:这些“坑”不是bug,只是自己当时没搞明白. 用到的框架为 Beego 1.字典 map 是“引用类型”,本身就是指针,作为参数传递时,直接传 map 变量名即可(不要传 map 变量指针). ...

  8. ASP.NET Web API实现缓存的2种方式

    在ASP.NET Web API中实现缓存大致有2种思路.一种是通过ETag, 一种是通过类似ASP.NET MVC中的OutputCache. 通过ETag实现缓存 首先安装cachecow.ser ...

  9. 内核同步机制-RCU同步机制

    转自:https://blog.csdn.net/nevil/article/details/7718375 转自http://www.360doc.com/content/09/0805/00/36 ...

  10. Tomcat增加虚拟内存(转)

    程序要遍历读取xml并写入数据库,需要占用大量内存 如果数据量大则报错 Exception in thread "Timer-0" java.lang.OutOfMemoryErr ...