C#知识点梳理补充

整个内容是我在春招面试时候整理的一些题目,里面涵盖有网上搬运的(因为当时没有记录来源,若是有转载没标注来源,请与我联系),还有我面试到的。整个排版很乱,后期我会一步一步整理。整个内容大概快有两万字。整理的过程也是自我知识体系梳理的过程,但愿能获得知识体系知识的提高。php

修改记录:css

2020/4/19 修改1~4html

1、基础知识前端

1 简单名词解释java

OOP:面向对象编程。面向过程能够理解成工厂里的流水线,封装的方式是按数据处理的流程。而面向对象更像是对工人的描述。将工人的工做方式封装成一个个的函数,而后让程序进行调用。jquery

OOD:面向对象设计。程序员

OOA:面向对象分析。web

高内聚:指一个软件模块是由相关性很强的代码组成,只负责一项任务,也就是常说的单一职责原则。面试

低耦合:简单理解,一个完整的系统,模块与模块之间,尽量的使其独立存在。让每个模块尽量独立完成某个特定的子功能。ajax

面向对象的好处:

(1)下降耦合。每一个功能分装成相应的类,下降功能之间代码上联系。

(2)提升可维护性。

2 封装

封装的优势:

(1)即隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别;将抽象获得的数据和行为(或功能)相结合,造成一个有机的总体,也就是将数据与操做数据的源代码进行有机的结合,造成“类”,其中数据和函数都是类的成员

(2)设计类时,不但愿直接存取类中的数据,而是但愿经过方法来存取数据。这样就能够达到封装数据的目的,方便之后的维护升级,也能够在操做数据时多一层判断。

(3)封装还能够解决数据存取的权限问题,能够使用封装将数据隐藏起来,造成一个封闭的空间,而后能够设置哪些数据只能在这个空间中使用,哪些数据能够在空间外部使用。一个类中包含敏感数据,有些人能够访问,有些人不能访问,若是不对这些数据的访问加以限制,后果将会很是严重。因此要对类的成员使用不一样的访问修饰符,从而定义他们的访问级别。

(4)经过修改访问修饰符实现

Public 数据类型 变量名
{
get{return 变量名}//获取数据
set{变量名=value;}//设置数据
}
使用封装还能够实现对属性的只读、只写:

public string Name { get; private set; }//只读
public string Name { private get; set; }//只写
这样写属性时,编译器会自动建立private string name。这种是会自动实现后备成员变量的自动实现属性。

若是是:

public string Name { get; set; }
这样的没有啥限定的属性,其实和公有字段没多大区别了。

3 继承

继承是面向对象最重要的特性之一。任何类均可以从另一个类继承,这就是说,这个类拥有它继承类的全部成员。在面向对象编程中,被继承的类称为父类或基类。C#中提供了类的继承机制,但只支持单继承,而不支持多继承,即在C#一次只容许继承一个类,不能同时继承多个类。

Public class 类名:父类名

如何使用父类里面的成员变量,方法,构造函数?

关键字:base

成员变量:base.成员变量名

方法:base.方法名

4 多态

多态性意味着有多重形式。在面向对象编程范式中,多态性每每表现为"一个接口,多个功能"。多态性能够是静态的或动态的。在静态多态性中,函数的响应是在编译时发生的。在动态多态性中,函数的响应是在运行时发生的。

4.1 静态多态性:在编译时,函数和对象的链接机制被称为早期绑定,也被称为静态绑定。C# 提供了两种技术来实现静态多态性。

(1)方法重载:能够在同一个范围内对相同的方法名有多个定义。方法的定义必须彼此不一样,能够是参数列表中的参数类型不一样,也能够是参数个数不一样。不能重载只有返回类型不一样的方法声明。

(2) 运算符重载:能够重定义或重载 C# 中内置的运算符

4.2 动态多态性:当有一个定义在类中的函数须要在继承类中实现时,能够使用虚方法。

4.2.1 虚方法(virtual)

(1)虚方法是使用关键字 virtual 声明的。

(2)虚方法能够在不一样的继承类中有不一样的实现。

(3)对虚方法的调用是在运行时发生的。

(4)动态多态性是经过抽象类和虚方法实现的。

4.2.2 接口(Interface)

接口和抽象类差很少,区别在于,接口内包含的所有是未实现的方法。并且接口类和方法的关键词不须要再声明abstract,接口类的关键词,interface,通常定义接口名称,按照约定,咱们会在名称前面加上一个I。例以下图的打印机接口。

虚方法:virtual
虚方法存在于相对于须要实现多态的子类的父类当中,同时也是实现多态的最基本的方法。
具体语法:父类的方法,用virtual修饰,表示虚方法。继承它的子类,在内部用override进行重写。下面进行案例分析:

4.2.3 抽象方法和抽象类
然而若是父类中的方法彻底不知道去干什么(即方法体中没有必要的代码),必需要子类进行重写才有意义的话,这种状况就须要使用抽象方法。说话,可是不一样的人会说不一样的话,这个时候就要用抽象类,先声明能够说话,可是不实现。

抽象方法和抽象类的关键字都是:abstract
若是父类的方法很抽象,并且没有具体的do(作什么)即方法体,必需要子类进行重写才有实际意义的话,这种状况就须要用抽象方法了。
父类、子类及输出:

C# 容许您使用关键字 abstract 建立抽象类,用于提供接口的部分类的实现。当一个派生类继承自该抽象类时,实现即完成。抽象类包含抽象方法,抽象方法可被派生类实现。派生类具备更专业的功能。
请注意,下面是有关抽象类的一些规则:
您不能建立一个抽象类的实例。
您不能在一个抽象类外部声明一个抽象方法。
经过在类定义前面放置关键字 sealed,能够将类声明为密封类。当一个类被声明为 sealed 时,它不能被继承。抽象类不能被声明为 sealed。
下面的程序演示了一个抽象类:
3.抽象方法的特色
    (1)只有方法头没有方法体的方法称之为抽象方法。(即只有方法的声明,没有方法的实现)
    (2)抽象方法用abstract关键字来修饰。
    (3)抽象方法表明一种不肯定的操做或行为。(由子类去具体实现)
    (4)抽象方法不能被调用。
4.抽象类的特色
    (1)定义中含有抽象方法的类叫作抽象类。
    (2)抽象类用abstract关键字来修饰。
    (3)抽象类表明一种抽象的对象类型。
    (4)抽象类不能实例化。
    (5)抽象类中能够有具体方法,能够没有抽象方法。(也就是说一个类中只要有一个方法是抽象方法那么这个类必定是抽象类,反过来,一个抽象类中能够没有抽象方法,能够带有具体
    实现的方法)
(6)一旦一个类中有抽象方法,那么这个类必须也要用abstract来修饰,表明这个类是抽象类,它是不能被实例化的。
抽象类是实现多态的方法之一,一个类被abstract标记的类叫抽象类。当父类的方法不知道如何去实现或者要把某个类抽象出来的时候,能够考虑将父类写成抽象类,将方法写成抽象方法,抽象类的成员也必须标记abstract,即抽象类不必定包含抽象方法,但抽象方法所在的类必定是抽象类,而且不能有任何实现,也就是没有方法体,抽象成员的访问修饰符能够不写,若是写,不能是private,实现父类抽象方法的方法的参数和返回值都要同样;
定义虚方法:
访问修饰符 virtual 返回的数据类型/void 方法名()
{
//执行代码,也能够彻底不写
}

重写父类的方法(子类中):
访问修饰符 override 返回的数据类型
void 方法名()
{
//执行代码
}

一、重载(overload): 在同一个做用域(通常指一个类)的两个或多个方法函数名相同,参数列表不一样的方法叫作重载,它们有三个特色(俗称两必须一能够):
方法名必须相同
参数列表必须不相同
返回值类型能够不相同

二、重写(override):子类中为知足本身的须要来重复定义某个方法的不一样实现,须要用 override 关键字,被重写的方法必须是虚方法,用的是 virtual 关键字。它的特色是(三个相同):相同的方法名、相同的参数列表、相同的返回值

二、虚方法:即为基类中定义的容许在派生类中重写的方法,使用virtual关键字定义。如:

3.抽象方法:在基类中定义的而且必须在派生类中重写的方法,使用 abstract 关键字定义。如:
注意:抽象方法只能在抽象类中定义,若是不在抽象类中定义,则会报出以下错误:
··················
一、值类型与引用类型
值类型:struct、enum、int、float、char、bool、decimal
什么是值类型:
进一步研究文档,你会发现全部的结构都是抽象类型System.ValueType的直接派生类,而System.ValueType自己又是直接从System.Object派生的。根据定义所知,全部的值类型都必须从System.ValueType派生,全部的枚举都从System.Enum抽象类派生,然后者又从System.ValueType派生。  
全部的值类型都是隐式密封的(sealed),目的是防止其余任何类型从值类型进行派生。       
基于值类型的变量直接包含值。 [2]  将一个值类型变量赋给另外一个值类型变量时,将复制包含的值。这与引用类型变量的赋值不一样,引用类型变量的赋值只复制对对象的引用,而不复制对象自己。
全部的值类型均隐式派生自SystemValueType。

引用类型:class、delegate、interface、array、object、string
在c#中全部的类都是引用类型,包括接口。
委托(Delegate)特别用于实现事件和回调方法。全部的委托(Delegate)都派生自 System.Delegate 类。

三、装箱与拆箱https://www.cnblogs.com/zjtao/p/11345442.html
四、一种最普通的场景是,调用一个含类型为Object的参数的方法,该Object可支持任意为型,以便通用。当你须要将一个值类型(如Int32)传入时,须要装箱。
另外一种用法是,一个非泛型的容器,一样是为了保证通用,而将元素类型定义为Object。因而,要将值类型数据加入容器时,须要装箱。
装箱:把值类型转换成引用类型
拆箱:把引用类型转换成值类型
装箱:对值类型在堆中分配一个对象实例,并将该值复制到新的对象中。
(1)第一步:新分配托管堆内存(大小为值类型实例大小加上一个方法表指针。
(2)第二步:将值类型的实例字段拷贝到新分配的内存中。
(3)第三步:返回托管堆中新分配对象的地址。这个地址就是一个指向对象的引用了。
拆箱:检查对象实例,确保它是给定值类型的一个装箱值。将该值从实例复制到值类型变量中。
在装箱时是不须要显式的类型转换的,不过拆箱须要显式的类型转换。

1.1 隐式数值转换
隐式数值转换包括如下几种:
●从sbyte类型到short,int,long,float,double,或decimal类型。
●从byte类型到short,ushort,int,uint,long,ulong,float,double,或decimal类型。
●从short类型到int,long,float,double,或decimal类型。
●从ushort类型到int,uint,long,ulong,float,double,或decimal类型。
●从int类型到long,float,double,或decimal类型。
●从uint类型到long,ulong,float,double,或decimal类型。
●从long类型到float,double,或decimal类型。
●从ulong类型到float,double,或decimal类型。
●从char类型到ushort,int,uint,long,ulong,float,double,或decimal类型。
●从float类型到double类型。
其中,从int,uint,或long到float以及从long到double的转换可能会致使精度降低,但决不会引发数量上的丢失。其它的隐式数值转换则不会

为何要使用集合?
数组的局限性:
(1)数组元素个数是固定的,数组一但定义,就没法改变元素总数。若是需求变化,则必须修改源码
(2)若是初始化元素总数很是大,则会形成空间浪费。
集合的特色:
(1)根据须要动态增长元素个数,没有限制。
(2)能够用以存储多个对象,这是个十分重要的属性。

泛型List

List泛型集合的特色:
(1)表示泛型,T是Type的简写,表示当前不肯定具体类型。
(2)能够根据用户的实际须要,肯定当前集合须要存放的数据类型,一旦肯定不可改变。
List泛型使用前的准备工做:
(1)引入命名空间:System.Collections.Generic
(2)肯定存储类型:List students = new List();

4堆和栈

五、栈是编译期间就分配好的内存空间,所以你的代码中必须就栈的大小有明确的定义,一般用于值类型;堆是程序运行期间动态分配的内存空间,你能够根据程序的运行状况肯定要分配的堆内存的大小
引用类型老是存放在堆中。
存放在栈中时要管存储顺序,保持着先进后出的原则,他是一片连续的内存域,有系统自动分配和维护;
堆是无序的,他是一片不连续的内存域,有用户本身来控制和释放,若是用户本身不释放的话,当内存达到必定的特定值时,经过垃圾回收器(GC)来回收。
栈内存无需咱们管理,也不受GC管理。当栈顶元素使用完毕,立马释放。而堆则须要GC清理。
使用引用类型的时候,通常是对指针进行的操做而非引用类型对象自己。可是值类型则操做其自己。

四、GC(Garbage Collection)
当程序须要更多的堆空间时,GC须要进行垃圾清理工做,暂停全部线程,找出全部无被引用的对象,进行清理,并通知栈中的指针从新指向地址排序后的对象。
GC只能处理托管内存资源的释放,对于非托管资源则不能使用GC进行回收,必须由程序员手动回收,例如FileStream或SqlConnection须要调用Dispose进行资源的回收。

五、CLR(Common Language Runtime)
公共语言运行库,负责资源管理(包括内存分配、程序及加载、异常处理、线程同步、垃圾回收等),并保证应用和底层操做系统的分离。

六、静态构造函数
最早被执行的构造函数,且在一个类里只容许有一个无参的静态构造函数
执行顺序:静态变量>静态构造函数>实例变量>实例构造函数
七、文件I/O
经过流的方式对文件进行读写操做
(1)FileStream
(2)StreamReader/StreamWriter
八、序列化与反序列化
序列化:将对象状态转换为可保持或传输的格式的过程。将对象实例的字段及类的名称转换成字节流,而后把字节流写入数据流。
经过序列化,能够执行以下操做:经过 Web 服务将对象发送到远程应用程序、在域之间传递对象、以 XML 字符串的形式传递对象经过防火墙、跨应用程序维护安全性或用户专属信息。
反序列化:将流转换为对象。
这两个过程结合起来,能够轻松地存储和传输数据。
九、线程同步
(1)方法一:阻塞(调用Sleep()或Join())
(2)方法二:加互斥锁lock

1 代码重用,继承类都能用抽象类定义的方法
2 灵活,某个继承类既能够继承改方法也能够派生一个新的
3 抽象类是全部继承类通用方法的最小集合,能够封装某一个继承类的实例用来进行传递

十、抽象类abstract class与接口interface的异同
相同点:
(1)均可以被继承
(2)都不能被实例化
(3)均可以包含方法的声明
不一样点:
(1)抽象类被子类继承;接口被类实现
(2)抽象类只能被单个类继承;接口可继承接口,并可多继承接口
(3)抽象基类能够定义字段、属性、方法实现;接口只能定义属性、索引器、事件、和方法声明,不能包含字段
(4)抽象类能够作方法声明,也可作方法实现;接口只能作方法声明
(5)具体派生类必须覆盖(override)抽象基类的抽象方法;派生类必须实现接口的全部方法
(6)抽象类是一个不完整的类,须要进一步细化;接口是一个行为规范
(7)抽象类中的虚方法或抽象方法必须用public修饰;接口中的全部成员默认为public,不能有private修饰符(也不能用public进行显示修饰)

1、
(1) 抽象方法只做声明,抽象类能够作方法声明,也可作方法实现;接口只能作方法声明
(2) 抽象类不能被实例化
(3) 抽象类能够但不是必须有抽象属性和抽象方法,可是一旦有了抽象方法,就必定要把这个类声明为抽象类
(4) 具体派生类必须覆盖基类的抽象方法
(5) 抽象派生类能够覆盖基类的抽象方法,也能够不覆盖。若是不覆盖,则其具体派生类必须覆盖它们。如:
2、接 口

(1) 接口不能被实例化
(2) 接口只能包含方法声明
(3) 接口的成员包括方法、属性、索引器、事件
(4) 接口中不能包含常量、字段(域)、构造函数、析构函数、静态成员。如:

十一、类class与结构体struct的异同
Class属于引用类型,是分配在内存的堆上的;
Struct属于值类型,是分配在内存的栈上的;不能从另一个结构或者类继承,自己也不能被继承;没有默认的构造函数,可是能够添加构造函数;能够不使用new 初始化

十二、using关键字的使用场景
(1)做为指令:用于导入其余命名空间中定义的类型或为命名空间建立别名
(2)做为语句:用于定义一个范围,在此范围的末尾将释放对象

1三、new关键字的使用场景
(1)实例化对象
(2)隐藏父类方法
(3)new约束指定泛型类声明中的任何类型参数都必须具备公共的无参数构造函数

1四、委托与事件
委托能够把一个方法做为参数传入另外一个方法,能够理解为指向一个函数的引用;
事件是一种特殊的委托。

1五、重载(overload)与重写(override)的区别
重载:是方法的名称相同,参数或参数类型不一样;重载是面向过程的概念。
重写:是对基类中的虚方法进行重写。重写是面向对象的概念。

1六、return执行顺序
try{} 里有一个return语句,那么finally{} 里的code在return前执行。

1七、switch(expression)
其中expression支持任何数据类型,包括null。
1八、反射Reflection
动态获取程序集信息。
1九、property与attribute的区别
property是属性,用于存取类的字段;
attribute是特性,用来标识类,方法等的附加性质。
20、访问修饰符
(1)public 公有访问,不受任何限制。
(2)private 私有访问,只限于本类成员访问。
(3)protected 保护访问,只限于本类和子类访问。
(4)internal 内部访问,只限于当前程序集内访问。
2一、static关键字的应用
对类有意义的字段和方法使用static关键字修饰,称为静态成员,经过类名加访问操做符“.”进行访问; 对类的实例有意义的字段和方法不加static关键字,称为非静态成员或实例成员。
注: 静态字段在内存中只有一个拷贝,非静态字段则是在每一个实例对象中拥有一个拷贝。而方法不管是否为静态,在内存中只会有一份拷贝,区别只是经过类名来访问仍是经过实例名来访问。
2三、值传递与引用传递
值传递时,系统首先为被调用方法的形参分配内存空间,并将实参的值按位置一一对应地复制给形参,此后,被调用方法中形参值得任何改变都不会影响到相应的实参;
引用传递时,系统不是将实参自己的值复制后传递给形参,而是将其引用值(即地址值)传递给形参,所以,形参所引用的该地址上的变量与传递的实参相同,方法体内相应形参值得任何改变都将影响到做为引用传递的实参。
简而言之,按值传递不是值参数是值类型,而是指形参变量会复制实参变量,也就是会在栈上多建立一个相同的变量。而按引用传递则不会。能够经过 ref 和 out 来决定参数是否按照引用传递。
2四、参数传递 ref 与 out 的区别
(1)ref指定的参数在函数调用时必须先初始化,而out不用
(2)out指定的参数在进入函数时会清空本身,所以必须在函数内部进行初始化赋值操做,而ref不用
总结:ref能够把值传到方法里,也能够把值传到方法外;out只能够把值传到方法外
注意:string做为特殊的引用类型,其操做是与值类型看齐的,若要将方法内对形参赋值后的结果传递出来,须要加上ref或out关键字。

3、数据库
http://www.javashuo.com/article/p-ywfrehrb-kq.html

通用数据库链接流程
第一,使用SqlConnection对象链接数据库;
第二,创建SqlCommand对象,负责SQL语句的执行和存储过程的调用;
第三,对SQL或存储过程执行后返回的“结果”进行操做。
对返回“结果”的操做能够分为两类:
一是用SqlDataReader直接一行一行的读取数据集;
二是DataSet联合SqlDataAdapter来操做数据库。

经常使用方法:
command.ExecuteNonQuery(): 返回受影响函数,如增、删、改操做;
command.ExecuteScalar():执行查询,返回首行首列的结果;
command.ExecuteReader():返回一个数据流(SqlDataReader对象)。

六、DataSet对象
6.1 SqlDataAdapter;
命名空间:System.Data.SqlClient.SqlDataAdapter;
SqlDataAdapter是SqlCommand和DataSet之间的桥梁,实例化SqlDataAdapter对象:
SqlConnection sqlCnt = new SqlConnection(connectString);
sqlCnt.Open();

// 建立SqlCommand
SqlCommand mySqlCommand = new SqlCommand();
mySqlCommand.CommandType = CommandType.Text;
mySqlCommand.CommandText = "select * from product";
mySqlCommand.Connection = sqlCnt;

// 建立SqlDataAdapter
SqlDataAdapter myDataAdapter = new SqlDataAdapter();
myDataAdapter.SelectCommand = mySqlCommand; // 为SqlDataAdapter对象绑定所要执行的SqlCommand对象
上述SQL能够简化为
SqlConnection sqlCnt = new SqlConnection(connectString);
sqlCnt.Open();
// 隐藏了SqlCommand对象的定义,同时隐藏了SqlCommand对象与SqlDataAdapter对象的绑定
SqlDataAdapter myDataAdapter = new SqlDataAdapter("select * from product", sqlCnt);
属性和方法
myDataAdapter.SelectCommand属性:SqlCommand变量,封装Select语句;
myDataAdapter.InsertCommand属性:SqlCommand变量,封装Insert语句;
myDataAdapter.UpdateCommand属性:SqlCommand变量,封装Update语句;
myDataAdapter.DeleteCommand属性:SqlCommand变量,封装Delete语句。
myDataAdapter.fill():将执行结果填充到Dataset中,会隐藏打开SqlConnection并执行SQL等操做。
6.2 SqlCommandBuilder;
命名空间:System.Data.SqlClient.SqlCommandBuilder。
对DataSet的操做(更改、增长、删除)仅是在本地修改,若要提交到“数据库”中则须要SqlCommandBuilder对象。用于在客户端编辑完数据后,总体一次更新数据。具体用法以下:
SqlCommandBuilder mySqlCommandBuilder = new SqlCommandBuilder(myDataAdapter); // 为myDataAdapter赋予SqlCommandBuilder功能
myDataAdapter.Update(myDataSet, "表名"); // 向数据库提交更改后的DataSet,第二个参数为DataSet中的存储表名,并不是数据库中真实的表名(两者在多数状况下一致)。

6.3 DataSet
命名空间:System.Data.DataSet。
数据集,本地微型数据库,能够存储多张表。
使用DataSet第一步就是将SqlDataAdapter返回的数据集(表)填充到Dataset对象中:
SqlDataAdapter myDataAdapter = new SqlDataAdapter("select * from product", sqlCnt);
DataSet myDataSet = new DataSet(); // 建立DataSet
myDataAdapter.Fill(myDataSet, "product"); // 将返回的数据集做为“表”填入DataSet中,表名能够与数据库真实的表名不一样,并不影响后续的增、删、改等操做
① 访问DataSet中的数据
SqlDataAdapter myDataAdapter = new SqlDataAdapter("select * from product", sqlCnt);
DataSet myDataSet = new DataSet();
myDataAdapter.Fill(myDataSet, "product");

DataTable myTable = myDataSet.Tables["product"];
foreach (DataRow myRow in myTable.Rows) {
foreach (DataColumn myColumn in myTable.Columns) {
Console.WriteLine(myRow[myColumn]); //遍历表中的每一个单元格
}
}

4、
一、数据库操做的相关类
特定类:Connection,Command,CommandBuilder,DataAdapter,DataReader,Parameter,Transaction
共享类:DataSet,DataTable,DataRow,DataColumn,DataRealtion,Constraint,DataColumnMapping,DataTableMapping
(1)Connection:开启程序与数据库之间的链接。
(2)Command:对数据库发送一些指令。例如增删改查等指令,以及调用存在数据库中的存储过程等。
(3)DataAdapter:主要在数据源及DataSet 之间执行传输工做,经过Command 下达命令后,将取得的数据放进DataSet对象中。
(4)DataSet:这个对象可视为一个暂存区(Cache),能够把数据库中所查询到的数据保存起来,甚至能够将整个数据库显示出来,DataSet是放在内存中的。
备注:将DataAdapter对象当作DataSet 对象与数据源间传输数据的桥梁。DataSet包含若干DataTable、DataTableTable包含若干DataRow。
(5)DataReader:一笔向下循序的读取数据源中的数据。
总结:http://ADO.NET 使用Connection对象来链接数据库,使用Command或DataAdapter对象来执行SQL语句,并将执行的结果返回给DataReader或DataAdapter,而后再使用取得的DataReader或DataAdapter对象操做数据结果。
二、事务:将多个任务放在一块进行运行,将多个sql语句放在一块运行
三、索引
四、视图
五、存储过程
插入
string sqlconn = "Data Source=.;Initial Catalog=claa;Integrated Security=True";
using (SqlConnection sqlcon = new SqlConnection(sqlconn))
{
sqlcon.Open();
string text = "Insert into Class values('李四','我很快乐')";
using (SqlCommand conn = new SqlCommand(text,sqlcon))
{
int number= conn.ExecuteNonQuery();
删除
string sql = "delete from Class where Class.cName='李四'";
using (SqlCommand conn = new SqlCommand(sql, con))
{
int i= conn.ExecuteNonQuery();

string connectionString = "Data Source=.;Initial Catalog=db_buiness;Integrated Security=True";
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();

string commandText = "Update Class set  cName=‘张三’  where id=2 ";
            using (SqlCommand cmd = new SqlCommand(commandText,conn))
            {
              int num=  cmd.ExecuteNonQuery();

3、数据结构(经常使用的排序算法)
一、冒泡排序
(1)原理
(2)实现代码
二、快速排序
(1)原理
(2)实现代码
5、软件开发流程
需求分析 --> 概要设计 --> 详细设计 --> 编码 --> 测试 --> 交付 --> 验收 --> 维护
熟悉API接口应用,封装.OCX、.Dll组件开发。
1、DLL 与应用程序
动态连接库(也称为 DLL ,即为“ Dynamic Link Library ”的缩写)是 Microsoft Windows 最重要的组成要素之一,打开 Windows 系统文件夹,你会发现文件夹中有不少 DLL 文件, Windows 就是将一些主要的系统功能以 DLL 模块的形式实现。
动态连接库是不能直接执行的,也不能接收消息,它只是一个独立的文件,其中包含能被程序或其它 DLL 调用来完成必定操做的函数 ( 方法。注: C# 中通常称为“方法” ) ,但这些函数不是执行程序自己的一部分,而是根据进程的须要按需载入,此时才能发挥做用。
DLL 只有在应用程序须要时才被系统加载到进程的虚拟空间中,成为调用进程的一部分,此时该 DLL 也只能被该进程的线程访问,它的句柄能够被调用进程所使用,而调用进程的句柄也能够被该 DLL 所使用。在内存中,一个 DLL 只有一个实例,且它的编制与具体的编程语言和编译器都没有关系,因此能够经过 DLL 来实现混合语言编程。 DLL 函数中的代码所建立的任何对象(包括变量)都归调用它的线程或进程全部。
下面列出了当程序使用 DLL 时提供的一些优势: [1]
1)  使用较少的资源
当多个程序使用同一个函数库时, DLL 能够减小在磁盘和物理内存中加载的代码的重复量。这不只能够大大影响在前台运行的程序,并且能够大大影响其余在 Windows 操做系统上运行的程序。
2)  推广模块式体系结构
DLL 有助于促进模块式程序的开发。这能够帮助您开发要求提供多个语言版本的大型程序或要求具备模块式体系结构的程序。模块式程序的一个示例是具备多个能够在运行时动态加载的模块的计账程序。
3)  简化部署和安装
当 DLL 中的函数须要更新或修复时,部署和安装 DLL 不要求从新创建程序与该 DLL 的连接。此外,若是多个程序使用同一个 DLL ,那么多个程序都将从该更新或修复中获益。当您使用按期更新或修复的第三方 DLL 时,此问题可能会更频繁地出现。
1.封装本身的dll;
a.打开visual studio - 文件 - 新建 - 项目- 类库 - 名称MyTestDll;
b.右键Class1.cs - 修改成 TestDll.cs;
c.在里面写一个方法,如:
namespace MyTestDll
{
  public static class TestDll where T:IComparable
  {
    ///


    /// 比较两个对象的大小
    ///

    ///
    ///
    public static T Maximun(T t1, T t2)
    {
      try
      {
        if (t1.CompareTo(t2) > 0)
        {
          return t1;
        }
        else
        {
          return t2;
        }
      }
      catch (System.Exception ex)
      {
        return default(T);
      }
    }
  }
}
d.保存 - 生成解决方案;
e.在Debug文件夹下就会有一个MyTestDll.dll文件,把它放在须要引用的工程;
 
2.调用装的dll文件;
a.打开visual studio - 文件 - 新建 - 项目- 控制台应用程序;
b.将MyTestDll.dll文件放在DeBug文件夹下面;
c.引用 - 添加引用 - 浏览 - 将MyTestDll.dll添加进来;

d.引用命令空间using MyTestDll;

主程序代码:
static void Main(string[] args)
{
  int var = TestDll .Maximun(1,2);
  Console.WriteLine("{0}", var);
  Console.ReadKey();
}
运行结果:
 
按F2查看封装的TestDll .Maximun方法,如图:

6、其余(了解)
一、.NET Core 与 .NET Framework 的区别
.NET Core 就是 .NET Framework 的开源且跨平台版本。但微软毕竟不能维护两个不一样的分支,一个跑在Windows上,一个跑在Linux(Unix Like)系统上,因此微软抽象出来一个标准库.NET Standard Library,.NET Core 与 .NET Framework 都必须实现标准库的API ,就这样.NET Core、.NET Framework、Xamarin成了三兄弟,分别为不一样的平台服务。

ASP.NET
ASP.NET 是新一代 ASP 。它与经典 ASP 是不兼容的,但 ASP.NET 可能包括经典 ASP。
ASP.NET 页面是通过编译的,这使得它们的运行速度比经典 ASP 快。
ASP.NET 具备更好的语言支持,有一大套的用户控件和基于 XML 的组件,并集成了用户身份验证。
ASP.NET 页面的扩展名是 .aspx ,一般是用 VB (Visual Basic) 或者 C# (C sharp) 编写。
在 ASP.NET 中的控件能够用不一样的语言(包括 C++ 和 Java)编写。
当浏览器请求 ASP.NET 文件时,ASP.NET 引擎读取文件,编译和执行脚本文件,并将结果以普通的 HTML 页面返回给浏览器。

WinService、WebService开发

2、字段的使用
1.关于字段
a.字段又称为:“成员变量”,通常在类的内部作数据交互使用。
b.字段命名规范:camel命名法(首单词字母小写)。
 
2.通俗的理解:
私有化:字段就比如咱们的我的财产,仅供我的使用,因此通常是private修饰。
添加标准:根据程序的功能需求,具体来添加须要的不一样类型的字段。

4、属性
1.属性的使用
做用:在面向对象设计中主要使用属性描述对象的静态特征。
要求:通常采用Pascal命名法(首字母大写),数据类型要和对应的字段要一致。
 
2.属性的理解
a.属性其实就是外界访问私有字段的入口,属性自己不保存任何数据,在对属性赋值和读取的时候其实就是操做的对应私有字段。
图例:

b.属性本质其实就是一个方法,经过get和set方法来操做对应的字段,经过反编译工具咱们能够看出,如图:

1.大家对于应届毕业生的能力要求通常是多少,是要有完整的项目经历和扎实的基础知识之间,大家会选什么?
2.公司的在.net方向的技术栈主要在哪方面,实在winform桌面开发?
3.若是工做的话,我会在哪里工做,是在上海?

三层架构是哪三层
界面层(User Interface layer):也就是UI层
业务逻辑层(Business Logic Layer)
数据访问层(Data access layer):实现对于数据库数据的访问和数据存储
Model类库:实现各个实体类
一、 各层的任务 
数据访问层:使用ADO.NET中的数据操做类,为数据库中的每一个表,设计1个数据访问类。类中实现:记录的插入、删除、单条记录的查询、记录集的查询、单条记录的有无判断等基本的数据操做方法。对于通常的管理信息软件,此层的设计是相似的,包含的方法也基本相同。此层的任务是:封装每一个数据表的基本记录操做,为实现业务逻辑提供数据库访问基础。 
业务逻辑层:为用户的每一个功能模块,设计1个业务逻辑类,此时,须要利用相关的数据访问层类中,记录操做方法的特定集合,来实现每一个逻辑功能。 
界面层:根据用户的具体需求,为每一个功能模块,部署输入控件、操做控件和输出控件,并调用业务逻辑层中类的方法实现功能。 
二、 层之间的调用关系 
数据访问层的类,直接访问数据库,实现基本记录操做。 
业务逻辑层的类,调用相关的数据访问类,实现用户所需功能。 
界面层:部署控件后,调用业务逻辑层的类,实现功能。 
将应用程序的功能分层后,对于固定的DBMS,数据访问层基本能够不变,一旦用户的需求改变,首先修改业务逻辑层,界面层稍作改动便可。这种作法使程序的可复用性、可修改性,都获得了很好的改善,大大提升了软件工程的效率。

Html
HTML 是用来描述网页的一种语言。‘
HTML 标记标签一般被称为 HTML 标签 (HTML tag)。

层叠样式表(英文全称:Cascading Style Sheets)是一种用来表现HTML(标准通用标记语言的一个应用)或XML(标准通用标记语言的一个子集)等文件样式的计算机语言。CSS不只能够静态地修饰网页,还能够配合各类脚本语言动态地对网页各元素进行格式化。 [1] 
CSS 可以对网页中元素位置的排版进行像素级精确控制,支持几乎全部的字体字号样式,拥有对网页对象和模型样式编辑的能力。 [2]

JavaScript是一种属于网络的脚本语言,已经被普遍用于Web应用开发,经常使用来为网页添加各式各样的动态功能,为用户提供更流畅美观的浏览效果。一般JavaScript脚本是经过嵌入在HTML中来实现自身的功能的。

数据库用户和登陆名即相关又不相关

数据库访问效率优化方法:

C#网页端作后台

MVC模式与三层架构的区别
转载Fast_Snail 最后发布于2017-03-10 09:31:09 阅读数 1076  收藏
展开
以前老是混淆MVC表现模式和三层架构模式,为此记录下。
三层架构和MVC是有明显区别的,MVC应该是展示模式(三个加起来之后才是三层架构中的UI层) 三层架构(3-tier application) 一般意义上的三层架构就是将整个业务应用划分为:表现层(UI)、业务逻辑层(BLL)、数据访问层(DAL)。区分层次的目的即为了“高内聚,低耦合”的思想。 一、表现层(UI):通俗讲就是展示给用户的界面,即用户在使用一个系统的时候他的所见所得。    二、业务逻辑层(BLL):针对具体问题的操做,也能够说是对数据层的操做,对数据业务逻辑处理。    三、数据访问层(DAL):该层所作事务直接操做数据库,针对数据的增添、删除、修改、更新、查找等。 
MVC是 Model-View-Controller,严格说这三个加起来之后才是三层架构中的UI层,也就是说,MVC把三层架构中的UI层再度进行了分化,分红了控制器、视图、实体三个部分,控制器完成页面逻辑,经过实体来与界面层完成通话;而C层直接与三层中的BLL进行对话。

mvc能够是三层中的一个表现层框架,属于表现层。三层和mvc能够共存。 三层是基于业务逻辑来分的,而mvc是基于页面来分的。 MVC主要用于表现层,3层主要用于体系架构,3层通常是表现层、中间层、数据层,其中表现层又能够分红M、V、C,(Model View Controller)模型-视图-控制器 
曾把MVC模式和Web开发中的三层结构的概念混为一谈,直到今天才发现一直是个人理解错误。MVC模式是GUI界面开发的指导模式,基于表现层分离的思想把程序分为三大部分:Model-View-Controller,呈三角形结构。Model是指数据以及应用程序逻辑,View是指 Model的视图,也就是用户界面。这二者都很好理解,关键点在于Controller的角色以及三者之间的关系。在MVC模式中,Controller和View同属于表现层,一般成对出现。Controller被设计为处理用户交互的逻辑。一个一般的误解是认为Controller负责处理View和Model的交互,而实际上View和Model之间是能够直接通讯的。因为用户的交互一般会涉及到Model的改变和View的更新,因此这些能够认为是Controller的反作用。
MVC是表现层的架构,MVC的Model其实是ViewModel,即供View进行展现的数据。 ViewModel不包含业务逻辑,也不包含数据读取。 而在N层架构中,通常还会有一个Model层,用来与数据库的表相对应,也就是所谓ORM中的O。这个Model多是POCO,也多是包含一些验证逻辑的实体类,通常也不包含数据读取。进行数据读取的是数据访问层。而做为UI层的MVC通常不直接操做数据访问层,中间会有一个业务逻辑层封装业务逻辑、调用数据访问层。UI层(Controller)经过业务逻辑层来获得数据(Model),并进行封装(ViewModel),而后选择相应的View。
MVC原本是存在于Desktop程序中的,M是指数据模型,V是指用户界面,C则是控制器。使用MVC的目的是将M和V的实现代码分离,从而使同一个程序能够使用不一样的表现形式。好比一批统计数据你能够分别用柱状图、饼图来表示。C存在的目的则是确保M和V的同步,一旦M改变,V应该同步更新。 MVC如何工做 MVC是一个设计模式,它强制性的使应用程序的输入、处理和输出分开。使用MVC应用程序被分红三个核心部件:模型、视图、控制器。它们各自处理本身的任务。 视图V 视图是用户看到并与之交互的界面。对老式的Web应用程序来讲,视图就是由HTML元素组成的界面,在新式的Web应用程序中,HTML依旧在视图中扮演着重要的角色,但一些新的技术已层出不穷,它们包括Macromedia Flash和象XHTML,XML/XSL,WML等一些标识语言和Web services. 如何处理应用程序的界面变得愈来愈有挑战性。MVC一个大的好处是它能为你的应用程序处理不少不一样的视图。在视图中其实没有真正的处理发生,无论这些数据是联机存储的仍是一个雇员列表,做为视图来说,它只是做为一种输出数据并容许用户操纵的方式。 模型M 模型表示企业数据和业务规则。在MVC的三个部件中,模型拥有最多的处理任务。被模型返回的数据是中立的,就是说模型与数据格式无关,这样一个模型能为多个视图提供数据。因为应用于模型的代码只需写一次就能够被多个视图重用,因此减小了代码的重复性。 控制器C 控制器接受用户的输入并调用模型和视图去完成用户的需求。因此当单击Web页面中的超连接和发送HTML表单时,控制器自己不输出任何东西和作任何处理。它只是接收请求并决定调用哪一个模型构件去处理请求,而后再肯定用哪一个视图来显示返回的数据。
模型Model 模型是应用程序的主体部分。模型表示业务数据,或者业务逻辑. 实现具体的业务逻辑、状态管理的功能。 视图View 视图是应用程序中用户界面相关的部分,是用户看到并与之交互的界面。 就是与用户实现交互的页面,一般实现数据的输入和输出功能。 控制器controller 控制器工做就是根据用户的输入,控制用户界面数据显示和更新model对象状态。起到控制整个业务流程的做用,实现View层跟Model层的协同工做。
3层架构指:表现层(显示层) 业务逻辑层 数据访问层(持久化)若是你们非要“生搬硬套”把它和MVC扯上关系话那我就只能在这里"强扭这个瓜"了即: V 3层架构中"表现层"aspx页面对应MVC中View(继承的类不同) C 三层架构中"表现层"的aspx.cs页面(类)对应MVC中的Controller,理解这一点并不难,你们想想咱们之前写过的 Redirect,固然它自己就是跳转了一些连接页面,而MVC中的Controller要作的更爽,它控制并显示输出了一个视图。即然所起到的做用都是对业务流程和显示信息的控制,只不过是实现手段不一样而已。 M 3层架构中业务逻辑层和数据访问层对应MVC中Model(一定View和Controller已找到“婆家”剩下Model只能是业务逻辑层和数据访问层了)
为何要使用 MVC 大部分Web应用程序都是用像ASP,PHP,或者CFML这样的过程化(自PHP5.0版本后已全面支持面向对象模型)语言来建立的。它们将像数据库查询语句这样的数据层代码和像HTML这样的表示层代码混在一块儿。经验比较丰富的开发者会将数据从表示层分离开来,但这一般不是很容易作到的,它须要精心的计划和不断的尝试。MVC从根本上强制性的将它们分开。尽管构造MVC应用程序须要一些额外的工做,可是它给咱们带来的好处是无庸质疑的。 首先,最重要的一点是多个视图能共享一个模型,如今须要用愈来愈多的方式来访问你的应用程序。对此,其中一个解决之道是使用MVC,不管你的用户想要Flash界面或是 WAP 界面;用一个模型就能处理它们。因为你已经将数据和业务规则从表示层分开,因此你能够最大化的重用你的代码了。 因为模型返回的数据没有进行格式化,因此一样的构件能被不一样界面使用。例如,不少数据可能用HTML来表示,可是它们也有可能要用Adobe Flash和WAP来表示。模型也有状态管理和数据持久性处理的功能,例如,基于会话的购物车和电子商务过程也能被Flash网站或者无线联网的应用程序所重用。 由于模型是自包含的,而且与控制器和视图相分离,因此很容易改变你的应用程序的数据层和业务规则。若是你想把你的数据库从MySQL移植到Oracle,或者改变你的基于RDBMS数据源到LDAP,只需改变你的模型便可。一旦你正确的实现了模型,无论你的数据来自数据库或是LDAP服务器,视图将会正确的显示它们。因为运用MVC的应用程序的三个部件是相互独立,改变其中一个不会影响其它两个,因此依据这种设计思想你能构造良好的松耦合的构件。 对我来讲,控制器也提供了一个好处,就是能够使用控制器来联接不一样的模型和视图去完成用户的需求,这样控制器能够为构造应用程序提供强有力的手段。给定一些可重用的模型和视图,控制器能够根据用户的需求选择模型进行处理,而后选择视图将处理结果显示给用户。
拿一个简单的登录模块说,需求是你输入一个用户名、密码,若是输入的跟预先定义好的同样,那么就进入到正确页面,若是不同,就提示个错误信息“你Y别在这儿蒙我,输入的不对!”。 V 这个小小的模块中,起始的输入用户名密码的页面跟通过校验后显示的页面就至关于View C 而这里还须要一个controller页面,就是用于接收输入进来的用户名密码,还有通过校验后返回的一个flg(此flg就是用于判断你输入的是否正确,而跳转到相应的页面的) M 最后还缺一个Model,那么就是你那个用于校验的类了,他就是处理你输入的是否跟预先订好的同样不同的,以后返回一个flg。 这样就彻底实现了逻辑跟页面的分离,我页面无论你咋整,反正我就一个显示,而controller呢也无论你Model咋判断对不对,反正我给你了用户名跟密码,你就得给我整回来一个flg来,而Medol呢,则是反正你敢给我个用户名跟密码,我就给你整过去个flg
m 提供数据,数据之间的关系,转化等。并能够通知视图和控制器本身哪些地方发生了变化。 v 提供显示,能根据m的改变来更新本身 c 好比视图作了点击一个按钮,会先发给这个视图的控制器,而后这个控制器来决定作什么操做(让模型更新数据,控制视图改变) mvc是一个复合模式 mv,mc都是观察者模式 m内部的组件组合模式 vc之间是策略模式(能够随时更换不一样的控制器)
MVC模式是上世纪70年代提出,最初用于Smalltalk平台上的。 MVC是表现模式,是用来向用户展示的许多组建的一个模式(UI/Presentation Patten) MVC有三种角色: Model:用来储存数据的组件(与领域模型概念不一样,二者会相互交叉) View:从Model中获取数据进行内容展现的组件。一样的Model在不一样的View下可展现不一样的效果。获取Model的状态,而不对其进行操做。 Controller:接受并处理用户指令(操做Model(业务)),选择一个View进行操做。
MVC概述:协做 存在单向引用,例如Model不知道View和Controller的存在。View不知道Controller的存在。这就隔离了表现和数据。View和controller是单向引用。而实际中View和Controller也是有数据交互的。
MVC的重要特色是分离。两种分离: View和数据(Model)的分离 使用不一样的View对相同的数据进行展现;分离可视和不可视的组件,可以对Model进行独立测试。由于分离了可视组件减小了外部依赖利于测试。(数据库也是一种外部组件) View和表现逻辑(Controller)的分离 Controller是一个表现逻辑的组件,并不是一个业务逻辑组件。MVC能够做为表现模式也能够做为建构模式,意味这Controller也能够是业务逻辑。分离逻辑和具体展现,可以对逻辑进行独立测试。
MVC和三层架构 MVC与三层架构相似么? View-UI Layer  |   Controller-Bussiness Layer  |  Model-Data Access Layer 其实这样是错误的 MVC是表现模式(Presentation Pattern) 三层架构是典型的架构模式(Architecture Pattern) 三层架构的分层模式是典型的上下关系,上层依赖于下层。但MVC做为表现模式是不存在上下关系的,而是相互协做关系。即便将MVC看成架构模式,也不是分层模式。MVC和三层架构基本没有可比性,是应用于不一样领域的技术。
MVC模式与三层架构:
ui (view)←(contorller)


bll  (model)


三、列举ASP.NET 页面之间传递值的几种方式。

1.使用QueryString, 如....?id=1; response. Redirect()....

2.使用Session变量

3.使用Server.Transfer

4.Cookie传值

四、C#中的委托是什么?事件是否是一种委托?事件和委托的关系。

委托能够把一个方法做为参数代入另外一个方法。

委托能够理解为指向一个函数的指针。

委托和事件没有可比性,由于委托是类型,事件是对象,下面说的是委托的对象(用委托方式实现的事件)和(标准的event方式实现)事件的区别。事件的内部是用委托实现的。由于对于事件来说,外部只能“注册本身+=、注销本身-=”,外界不能够注销其余的注册者,外界不能够主动触发事件,所以若是用Delegate就无法进行上面的控制,所以诞生了事件这种语法。事件是用来阉割委托实例的,类比用一个自定义类阉割List。事件只能add、remove本身,不能赋值。事件只能+=、-=,不能= 。加分的补充回答:事件内部就是一个private的委托和add、remove两个方法

面试聊:用Reflector查看.Net的类的内部实现,解决问题。

五、override与重载(overload)的区别

重载是方法的名称相同。参数或参数类型不一样,进行屡次重载以适应不一样的须要。重载(overload)是面向过程的概念。

Override 是进行基类中函数的重写。Override是面向对象的概念

六、C#中索引器是否只能根据数字进行索引?是否容许多个索引器参数?

参数的个数和类型都是任意的。加分的补充回答:用reflector反编译能够看出,索引器的内部本质上就是set_item、get_item方法。

基础知识:

索引的语法:

public string this[string s],经过get、set块来定义取值、赋值的逻辑

索引能够有多个参数、参数类型任意

索引能够重载。

若是只有get没有set就是只读的索引。

索引其实就是set_Item、get_Item两个方法。

七、属性和public字段的区别是什么?调用set方法为一个属性设值,而后用get方法读取出来的值必定是set进去的值吗?

属性能够对设值、取值的过程进行非法值控制,好比年龄禁止设值负数,而字段则不能进行这样的设置。虽然通常状况下get读取的值就是set设置的值,可是可让get读取的值不是set设置的值的,极端的例子。Public Age{get{return 100;}set{}}。加分的补充回答:用reflector反编译能够看出,属性内部本质上就是set_、get_方法

class Person

{

public int Age

{

get

{

return 3;

}

set

{

}

}

}

Person p1 = new Person();

p1.Age = 30;

p1.Age++;

Console.Write(p1.Age);//输出3

必须手写掌握的代码(既包含拿电脑写,拿笔写):

手写三层架构
手写冒泡排序
手写AJAX:XMLHttpRequest
手写增删改查、SQLHelper
八、三层架构

一般意义上的三层架构就是将整个业务应用划分为:表现层(UI)、业务逻辑层(BLL)、数据访问层(DAL)。区分层次的目的即为了“高内聚,低耦合”的思想。表现层(UI):通俗讲就是展示给用户的界面,即用户在使用一个系统的时候的所见所得。业务逻辑层(BLL):针对具体问题的操做,也能够说是对数据层的操做,对数据业务逻辑处理。数据访问层(DAL):该层所作事务直接操做数据库,针对数据的增添、删除、修改、更新、查找等每层之间是一种垂直的关系。三层结构是N层结构的一种,通常来讲,层次之间是向下依赖的,下层代码未肯定其接口(契约)前,上层代码是没法开发的,下层代码接口(契约)的变化将使上层的代码一块儿变化。

优势: 分工明确,条理清晰,易于调试,并且具备可扩展性。

缺点: 增长成本。

九、什么是装箱(boxing)和拆箱(unboxing)? (*)

Object是引用类型,可是它的子类Int32居然不能去Object能去的“要求必须是引用类型”

的地方,违反了继承的原则,因此须要把Int32装在Object中才能传递。

装箱:从值类型接口转换到引用类型。

拆箱:从引用类型转换到值类型。

object obj = null;//引用类型

obj = 1;//装箱,boxing。把值类型包装为引用类型。

int i1 = (int)obj;//拆箱。unboxing

2)下面三句代码有没有错,以inboxing或者unboxing为例,解释一下内存是怎么变化的

int i=10;

object obj = i;

int j = obj;

分析:在inboxing(装箱)时是不须要显式的类型转换的,不过unboxing(拆箱)须要显式的类型转换,因此第三行代码应该改成:

3 int j = (int)obj;

要掌握装箱与拆箱,就必须了解CTS及它的特色:

NET重要技术和基础之一的CTS(Common Type System)。CTS是为了实如今应用程序声明和使用这些类型时必须遵循的规则而存在的通用类型系统。.Net将整个系统的类型分红两大类 :值类型和引用类型。

CTS中的全部东西都是对象;全部的对象都源自一个基类——System.Object类型。值类型的一个最大的特色是它们不能为null,值类型的变量总有一个值。为了解决值类型不能够为null,引用类型能够为null的问题,微软在.Net中引入了装箱和拆箱:装箱就是将值类型用引用类型包装起来转换为引用类型;而从引用类型中拿到被包装的值类型数据进行拆箱。

十、CTS、CLS、CLR分别做何解释(*)把英文全称背过来。

C#和.Net的关系。

C#只是抽象的语言,能够把C#编译生成Java平台的二进制代码,也能够把Java代码编译生成.Net平台的二进制代码。因此C#只是提供了if、while、+-*/、定义类、int、string等基础的语法,而Convert.ToInt3二、FileStream、SqlConnection、String.Split等都属于.Net的东西。深蓝色是C#的,浅蓝色是.Net的。

C# new→IL:newobj

C# string →.Net中的String

类型的差异:.net中的Int32在C#中是int,在VB.Net中是Integer。String、Int32等公共类型。

语法的差异:IL中建立一个对象的方法是L_0001: newobj instance void 索引.C1::.ctor()

C#中是new C1();VB.net中是 Dim c1 As New C1

CTS:Common Type System 通用类型系统。Int3二、Int16→int、String→string、Boolean→bool。每种语言都定义了本身的类型,.Net经过CTS提供了公共的类型,而后翻译生成对应的.Net类型。

CLS:Common Language Specification 通用语言规范。不一样语言语法的不一样。每种语言都有本身的语法,.Net经过CLS提供了公共的语法,而后不一样语言翻译生成对应的.Net语法。

CLR:Common Language Runtime 公共语言运行时,就是GC、JIT等这些。有不一样的CLR,好比服务器CLR、Linux CLR(Mono)、Silverlight CLR(CoreCLR)。至关于一个发动机,负责执行IL。

十一、在dotnet中类(class)与结构(struct)的异同?

Class能够被实例化,属于引用类型,是分配在内存的堆上的。类是引用传递的。

Struct属于值类型,是分配在内存的栈上的。结构体是复制传递的。加分的回答:Int3二、Boolean等都属于结构体

十二、堆和栈的区别?

栈是编译期间就分配好的内存空间,所以你的代码中必须就栈的大小有明确的定义;局部值类型变量、值类型参数等都在栈内存中。

堆是程序运行期间动态分配的内存空间,你能够根据程序的运行状况肯定要分配的堆内存的大小。

1三、能用foreach遍历访问的对象的要求

须要实现IEnumerable接口或声明GetEnumerator方法的类型。

1四、GC是什么? 为何要有GC?

C/C++中由程序员进行对象的回收像学校食堂中由学生收盘子,.Net中由GC进行垃圾回收像餐馆中店员去回收。

GC是垃圾收集器(Garbage Collection)。程序员不用担忧内存管理,由于垃圾收集器会自动进行管理。GC只能处理托管内存资源的释放,对于非托管资源则不能使用GC进行回收,必须由程序员手工回收,一个例子就是FileStream或者SqlConnection须要程序员调用Dispose进行资源的回收。

要请求垃圾收集,能够调用下面的方法:GC.Collect()通常不须要手动调用GC.Collect()。当一个对象没有任何变量指向(再也不能使用)的时候就能够被回收了。

基础知识:当没有任何变量指向一个对象的时候对象就能够被回收掉了,但不必定会当即被回收。

object obj = new object();//只有new才会有新对象

Console.WriteLine(obj);

object obj2 = obj;

obj = null;

obj2 = null;

Console.WriteLine();

1五、值类型和引用类型的区别?

1.将一个值类型变量赋给另外一个值类型变量时,将复制包含的值。引用类型变量的赋值只复制对对象的引用,而不复制对象自己。

2.值类型不可能派生出新的类型:全部的值类型均隐式派生自 System.ValueType。但与引用类型相同的是,结构也能够实现接口。

3.值类型不可能包含 null 值:然而,可空类型功能容许将 null 赋给值类型。

4.每种值类型均有一个隐式的默认构造函数来初始化该类型的默认值。

1六、C#中的接口和类有什么异同。

不一样点:

不能直接实例化接口。

接口不包含方法的实现。

接口能够多继承,类只能单继承。

类定义可在不一样的源文件之间进行拆分。

相同点:

接口、类和结构均可以从多个接口继承。

接口相似于抽象基类:继承接口的任何非抽象类型都必须实现接口的全部成员。

接口和类均可以包含事件、索引器、方法和属性。

基础知识:接口只能定义方法(只能定义行为,不能定义实现也就是字段),由于事件、索引器、属性本质上都是方法,因此接口中也能够定义事件、索引器、属性。

1七、abstract class和interface有什么区别?

相同点:

都不能被直接实例化,均可以经过继承实现其抽象方法。

不一样点:

接口支持多继承;抽象类不能实现多继承。

接口只能定义行为;抽象类既能够定义行为,还可能提供实现。

接口只包含方法(Method)、属性(Property)、索引器(Index)、事件(Event)的签名,但不能定义字段和包含实现的方法;

抽象类能够定义字段、属性、包含有实现的方法。

接口能够做用于值类型(Struct)和引用类型(Class);抽象类只能做用于引用类型。例如,Struct就能够继承接口,而不能继承类。

加分的补充回答:讲设计模式的时候SettingsProvider的例子。

1八、是否能够继承String类?

String类是sealed类故不能够继承。

1九、int、DateTime、string是否能够为null?

null表示“不知道”,而不是“没有”。没有年龄和不知道年龄是不同。

数据库中null不能用0表示。0岁和不知道多少岁不同。

Sex is zero。《色便是空》

//int i1 = null;

//int? i2 = null;//值类型后加?就成了可空数据类型

////int i3 = i2;//因此把可空的赋值给必定不能为空的会报错。

//int i4 = (int)i2;//能够显式转换,由程序员来保证“必定不为空”

//int? i5 = i4;//必定会成功!

//using()→try{]catch{}finally{}

//int?是微软的一个语法糖。是一种和int没有直接关系的Nullable类型

Nullable d1 = new Nullable ();//int? d1=null;

Nullable d2 = new Nullable (3);//int? d2=3;

Console.WriteLine(d1==null);

int、DateTime不能,由于其为Struct类型,而结构属于值类型,值类型不能为null,只有引用类型才能被赋值null。string能够为null。

C#中int等值类型不能够为null、而数据库中的int能够为null,这就是纠结的地方。int?就变成了可空的int类型。bool?、DateTime?

int i1 = 3;

int? i2 = i1;

//int i3 = i2;//不能把可能为空的赋值给必定不能为空的变量

int i3 = (int)i2;//显式转换

可空数据类型经典应用场景:三层中的Model属性的设计。

int?翻译生成.Net的Nullable ,CTS。

20、using关键字有什么用?什么是IDisposable?

using能够声明namespace的引入,还能够实现非托管资源的释放,实现了IDisposiable的类在using中建立,using结束后会自动调用该对象的Dispose方法,释放资源。加分的补充回答:using其实等价于try……finally,用起来更方便。

2一、XML 与 HTML 的主要区别

  1. XML是区分大小写字母的,HTML不区分。

  2. 在HTML中,若是上下文清楚地显示出段落或者列表键在何处结尾,那么你能够省略

    或者
  3. 之类的结束 标记。在XML中,绝对不能省略掉结束标记。

HTML:

XML:

  1. 在XML中,拥有单个标记而没有匹配的结束标记的元素必须用一个 / 字符做为结尾。这样分析器就知道不用 查找结束标记了。

  2. 在XML中,属性值必须分装在引号中。在HTML中,引号是可用可不用的。

  3. 在HTML中,能够拥有不带值的属性名。在XML中,全部的属性都必须带有相应的值。

XML是用来存储和传输数据的

HTML是用来显示数据的

若是使用了彻底符合XML语法要求的HTML,那么就叫作符合XHTML标准。符合XHTML标准的页面有利于SEO。

2二、string str = null 与 string str =””说明其中的区别。

答:string str = null 是不给他分配内存空间,而string str = "" 给它分配长度为空字符串的内存空间。 string str = null没有string对象,string str = “”有一个字符串对象。

string s3 = string.Empty;//反编译发现,string.Empty就是在类构造函数中 Empty = "";

2三、写出一条Sql语句:取出表A中第31到第40记录(SQLServer,以自动增加的ID做为主键,注意:ID可能不是连续的。

答:解1: select top 10 * from A where id not in (select top 30 id from A)

演变步骤:

1)select top 30 id from T_FilterWords--取前条

2)select * from T_FilterWords

where id not in (select top 30 id from T_FilterWords)--取id不等于前三十条的

--也就是把前条排除在外

3)select top 10 * from T_FilterWords

where id not in (select top 30 id from T_FilterWords)

--取把前条排除在外的前条,也就是-40条

解2: select top 10 * from A where id > (select max(id) from (select top 30 id from A )as A)

解答3:用ROW_NUMBER实现

2四、在.Net中全部可序列化的类都被标记为

[serializable]

2五、什么是code-Behind技术。

就是代码隐藏,在ASP.NET中经过ASPX页面指向CS文件的方法实现显示逻辑和处理逻辑的分离,这样有助于web应用程序的建立。好比分工,美工和编程的能够个干各的,不用再像之前asp那样都代码和html代码混在一块儿,难以维护。code-Behind是基于部分类技术实现的,在个人项目的三层代码生成器中用到了部分类。

2六、接口是一种引用类型,在接口中能够声明(   a),但不能够声明公有的域或私有的成员变量。   
  a) 方法、属性、索引器和事件;

b) 索引器和字段;    
  c) 事件和字段;

解读:接口中不能声明字段只能声明方法,属性、索引器和事件 最终都编译生成方法。由于字段属于实现层面的东西,只有存取值的时候才会用到字段,因此中接口中不能定义字段。

2七、在ADO.NET中,对于Command对象的ExecuteNonQuery()方法和ExecuteReader()方法,下面叙述错误的是(c)。  
  a) insert、update、delete等操做的Sql语句主要用ExecuteNonQuery()方法来执行;  
  b) ExecuteNonQuery()方法返回执行Sql语句所影响的行数。  
  c) Select操做的Sql语句只能由ExecuteReader()方法来执行;  
  d) ExecuteReader()方法返回一个DataReader对象;

拿SQLHelper实现一下。

2八、StringBuilder 和 String 的区别?

答:String 在进行运算时(如赋值、拼接等)会产生一个新的实例,而 StringBuilder 则不会。因此在大量字符串拼接或频繁对某一字符串进行操做时最好使用 StringBuilder,不要使用 String

若是要操做一个不断增加的字符串,尽可能不用String类,改用StringBuilder类。两个类的工做原理不一样:String类是一种传统的修改字符串的方式,它确实能够完成把一个字符串添加到另外一个字符串上的工做没错,可是在.NET框架下,这个操做实在是划不来。由于系统先是把两个字符串写入内存,接着删除原来的String对象,而后建立一个String对象,并读取内存中的数据赋给该对象。这一来二去的,耗了很多时间。而使用System.Text命名空间下面的StringBuilder类就不是这样了,它提供的Append方法,可以在已有对象的原地进行字符串的修改,简单并且直接。固然,通常状况下觉察不到这两者效率的差别,但若是你要对某个字符串进行大量的添加操做,那么StringBuilder类所耗费的时间和String类简直不是一个数量级的。

2九、请叙述属性与索引器的区别。 (*)

属性 索引器

经过名称标识。 经过签名标识。

经过简单名称或成员访问来访问。 经过元素访问来访问。

能够为静态成员或实例成员。 必须为实例成员。

属性的   get   访问器没有参数。 索引器的   get   访问器具备与索引器相同的形参表。

属性的   set   访问器包含隐式   value   参数。 除了   value   参数外,索引器的 set 访问器还具备与索引器相同的形参表。

30、请解释ASP。NET中的web页面与其隐藏类之间的关系?

一个ASP.NET页面通常都对应一个隐藏类,通常都在ASP.NET页面的声明中指定了隐藏类例如一个页面Tst1.aspx的页面声明以下

<%@ Page language="c#" Codebehind="Tst1.aspx.cs" AutoEventWireup="false" Inherits="T1.Tst1" %>

Codebehind="Tst1.aspx.cs" 代表经编译此页面时使用哪个代码文件

Inherits="T1.Tst1" 表用运行时使用哪个隐藏类

aspx页面会编译生成一个类,这个类从隐藏类继承。

3一、您在什么状况下会用到虚方法?它与接口有什么不一样?

答案:子类从新定义父类的某一个方法时,必须把父类的方法定义为virtual

在定义接口中不能有方法体,虚方法能够。

实现时,子类能够不从新定义虚方法,但若是一个类继承接口,那必须实现这个接口。

3二、DataReader和DataSet的异同?

DataReader使用时始终占用SqlConnection,在线操做数据库

每次只在内存中加载一条数据,因此占用的内存是很小的

是只进的、 只读的

DataSet则是将数据一次性加载在内存中.抛弃数据库链接..读取完毕即放弃数据库链接(非链接模式)

DataSet将数据所有加载在内存中.因此比较消耗内存...可是确比DataReader要灵活..能够动态的添加行,列,数据.对数据库进行 回传更新操做(动态操做读入到内存的数据)

3三、public static const int  A = 1;这段代码有错误么?

错误:const不能被修饰为static ;由于定义为常量 (const )后就是静态的(static )。

3四、传入某个属性的set方法的隐含参数的名称是什么?

value,它的类型和属性所声名的类型相同。

3五、C#支持多重继承么?

类之间不支持,接口之间支持。类对接口叫作实现,不叫继承。 类是爹、接口是能力,能有多个能力,但不能有多个爹。

3六、C#中全部对象共同的基类是什么?

System.Object

3七、经过超连接怎样传递中文参数?

答:用URL编码,经过QueryString传递,用urlencode编码 用urldecode解码

3八、string、String;int、Int32;Boolean、bool的区别

String、Int3二、Boolean等都属于.Net中定义的类,而string、int、bool至关于C#中对这些类定义的别名。CTS。

3九、Server.Transfer和Response.Redirect的区别是什么?(常考)

答: Server.Transfer仅是服务器中控制权的转向,在客户端浏览器地址栏中不会显示出转向后的地址;Response.Redirect则是彻底的跳转,浏览器将会获得跳转的地址,并从新发送请求连接。这样,从浏览器的地址栏中能够看到跳转后的连接地址。

Server.Transfer是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,而后把这些内容再发给浏览器,浏览器根本不知道服务器发送的内容是从哪儿来的,因此它的地址栏中仍是原来的地址。 这个过程当中浏览器和Web服务器之间通过了一次交互。

Response.Redirect就是服务端根据逻辑,发送一个状态码,告诉浏览器从新去请求那个地址,通常来讲浏览器会用刚才请求的全部参数从新请求。这个过程当中浏览器和Web服务器之间通过了两次交互。

Server.Transfer不能够转向外部网站,而Response.Redirect能够。

Server.Execute效果和Server.Transfer相似,可是是把执行的结果嵌入当前页面。

40、不是说字符串是不可变的吗?string s="abc";s="123"不就是变了吗?

String是不可变的在这段代码中,s原先指向一个String对象,内容是 "abc",而后咱们将s指向"123",那么s所指向的那个对象是否发生了改变呢?答案是没有。这时,s不指向原来那个对象了,而指向了另外一个 String对象,内容为"123",原来那个对象还存在于内存之中,只是s这个引用变量再也不指向它了。

4一、是否能够从一个static方法内部发出对非static方法的调用?

不能够。由于非static方法是要与对象关联在一块儿的,必须建立一个对象后,才能够在该对象上进行方法调用,而static方法调用时不须要建立对象,能够直接调用。也就是说,当一个static方法被调用时,可能尚未建立任何实例对象,若是从一个static方法中发出对非static方法的调用,那个非static方法是关联到哪一个对象上的呢?这个逻辑没法成立,因此,一个static方法内部不能发出对非static方法的调用。

4二、说出一些经常使用的类、接口,请各举5个

要让人家感受你对.Net开发很熟,因此,不能仅仅只列谁都能想到的那些东西,要多列你在作项目中涉及的那些东西。就写你最近写的那些程序中涉及的那些类。

经常使用的类:StreamReader、WebClient、Dictionary<K,V>、StringBuilder、SqlConnection、FileStream、File、Regex、List

经常使用的接口:IDisposable、IEnumerable、IDbConnection、IComparable、ICollection、IList、IDictionary

要出乎意料!不要仅仅完成任务!笔试不是高考!到处要显出牛!

说出几个开源软件?MySQL、Linux、 Discuz、Apache、Paint.Net、Android、Chrome、Notepad++……

开源项目有一些是开发包。开源软件指的是能够直接用的。Jquery、NPOI、ASP.Net MVC、Silverlight  Toolkit、AJAX toolkit、json.net

4三、编写一个单例(Singleton)类。

把构造函数设置为private,设置一个public、static的对象实例

public FileManager

{

private FileManager(){}

public readonly static FileManager Instance = new FileManager();

}

扩展:搜“C#  Singleton”,有线程安全的更牛B的实现

4四、什么是sql注入?如何避免sql注入?

用户根据系统的程序构造非法的参数从而致使程序执行不是程序员指望的恶意SQL语句。使用参数化的SQL就能够避免SQL注入。

详细参考复习ppt。举例子,摆事实!

1' or 1=1

4五、数据库三范式是什么?

用本身的话解释,而不是背概念。

第一范式:字段不能有冗余信息,全部字段都是必不可少的。

第二范式:知足第一范式而且表必须有主键。

第三范式:知足第二范式而且表引用其余的表必须经过主键引用。

员工内部→本身的老大→外部的老大

记忆顺序:本身内部不重复→别人引用本身→本身引用别人。

4六、post、get的区别

get的参数会显示在浏览器地址栏中,而post的参数不会显示在浏览器地址栏中;

使用post提交的页面在点击【刷新】按钮的时候浏览器通常会提示“是否从新提交”,而get则不会;

用get的页面能够被搜索引擎抓取,而用post的则不能够;

用post能够提交的数据量很是大,而用get能够提交的数据量则很是小(2k),受限于网页地址的长度。

用post能够进行文件的提交,而用get则不能够。

参考阅读:http://www.cnblogs.com/skynet/archive/2010/05/18/1738301.html

4七、.Net、ASP.Net、C#、VisualStudio之间的关系是什么?

答:.Net通常指的是.Net Framework,提供了基础的.Net类,这些类能够被任何一种.Net编程语言调用,.Net Framework还提供了CLR、JIT、GC等基础功能。

ASP.Net是.Net中用来进行Web开发的一种技术,ASP.Net的页面部分写在aspx 文件中,逻辑代码一般经过Code-behind的方式用C#、VB.Net等支持.Net的语言编写。

C#是使用最普遍的支持.Net的编程语言。除了C#还有VB.Net、IronPython等。

VisualStudio是微软提供的用来进行.Net开发的集成开发环境(IDE),使用VisualStudio能够简化不少工做,不用程序员直接调用csc.exe等命令行进行程序的编译,并且VisualStudio提供了代码自动完成、代码高亮等功能方便开发。除了VisualStudio,还有SharpDevelop、MonoDevelop等免费、开源的IDE,VisualStudio Express版这个免费版本。

4八、AJAX解决什么问题?如何使用AJAX?AJAX有什么问题须要注意?项目中哪里用到了AJAX?

答:AJAX解决的问题就是“无刷新更新页面”,用传统的HTML表单方式进行页面的更新时,每次都要将请求提交到服务器,服务器返回后再重绘界面,这样界面就会经历:提交→变白→从新显示这样一个过程,用户体验很是差,使用AJAX则不会致使页面从新提交、刷新。

AJAX最本质的实现是在Javascript中使用XMLHttpRequest进行Http的请求,开发中一般使用UpdatePanel、JQuery等方式简化AJAX的开发,UpdatePanel的方式实现AJAX最简单,可是数据通信量比较大,由于要来回传整个ViewState,并且不灵活,对于复杂的需求则能够使用JQuery提供的ajax功能。

UpdatePanel的内部原理。

AJAX最重要的问题是没法跨域请求(www.rupeng.com →so.rupeng.com),也就是没法在页面中向和当前域名不一样的页面发送请求,能够使用在当前页面所在的域的服务端作代理页面的方式解决。

在如鹏网项目中发帖的时候显示相关帖的功能、站内搜索项目中显示搜索Suggestion、数据采集项目中都用到了AJAX。

常考:不用任何框架编写一个AJAX程序。XHR:XmlHttpRequest。背也要背下来!

若是面试的时候谈AJAX谈到UpdatePanel的时候,就是NB的时候!!!先侃UpdatePanel的原理!引出为何Dom操做的动态效果在用UpdatePanel提交刷新之后没有了,以及CKEditor被套在UpdatePanel中提交之后也变成了textarea,为何把Fileupload放到Updatepanel中没法实现无刷新上传。说成是公司内部的一个菜鸟用UpdatePanel遇到这样问题,因为我懂XHR、UpdatePanel的原理,因此轻松解决!UpdatePanel生成的上万行JS脚本,不适合于互联网项目。“WebForm怎么可能把开发人员编程傻子呢!不明白原理苦命呀!仍是MVC好呀,MVC。。。。。。。”

4九、Application 、Cookie和 Session 两种会话有什么不一样?

答:Application是用来存取整个网站全局的信息,而Session是用来存取与具体某个访问者关联的信息。Cookie是保存在客户端的,机密信息不能保存在Cookie中,只能放小数据;Session是保存在服务器端的,比较安全,能够放大数据。

谈到Session的时候就侃Session和Cookie的关系:Cookie中的SessionId。和别人对比说本身懂这个原理而给工做带来的方便之处。

50、开放式问题:你常常访问的技术类的网站是什么?

博客园(www.cnblogs.com)、csdn、codeplex、codeproject、msdn文档、msdn论坛(遇到问题先到网上搜解决方案,还不行就问同事,同事也解决不了就去MSDN论坛提问,必定能获得解决)。Cnbeta.com。

8、数据库优化经验(后端工程师很是常见)
出现指数:四颗星
主要考点:此题考察后端工程师操做数据库的经验。说实话,数据库是博主的弱项,博主以为对于这种考题,须要抓住几个经常使用而且关键的优化经验,若是说得不对,欢迎你们斧正。
参考答案:
一、数据库运维方面的优化:启用数据库缓存。对于一些比较经常使用的查询能够采用数据库缓存的机制,部署的时候须要注意设置好缓存依赖项,防止“过时”数据的产生。
二、数据库索引方面的优化:好比经常使用的字段建索引,联合查询考虑联合索引。(PS:若是你有基础,能够敞开谈谈汇集索引和非汇集索引的使用场景和区别)
三、数据库查询方面的优化:避免select * 的写法、尽可能不用in和not in 这种耗性能的用法等等。
四、数据库算法方面的优化:尽可能避免大事务操做、减小循环算法,对于大数据量的操做,避免使用游标的用法等等。

一、什么是面向对象?
面向对象说到底就是一种思想,任何事物均可以看做是一个对象。在有些面试题目中也称之为OOP(Object Oriented Programming)。分开来解读就是:
Object:对象
Oriented: 面向的
Programming:程序设计
面向对象就是把一我的或事务的属性,好比名字,年龄这些定义在一个实体类里面。存和取的时候直接使用存取实体类就把这我的的名字,年龄这些所有存了,这个实体类就叫对象,这种思想就叫面向对象。
面向对象开发具备如下优势:
    代码开发模块化,便于维护。
    代码复用性强
    代码的可靠性和灵活性。
    代码的可读性和可扩展性。

1、对于 Web 性能优化,您有哪些了解和经验吗?
出现指数:五颗星
主要考点:这道题是博主在博客园的新闻里面看到的,回想以前几年的面试经历,发现此题出现几率仍是比较高的。由于它的考面灰常广,可让面试官很快了解你的技术涉及面以及这些技术面的深度。
参考答案:这个问题能够分前端和后端来讲。
一、前端优化
(1)减小 HTTP 请求的次数。咱们知道每次发送http请求,创建链接和等待相应会花去至关一部分时间,因此在发送http请求的时候,尽可能减小请求的次数,一次请求能取出的数据就不要分屡次发送。
(2)启用浏览器缓存,当肯定请求的数据不会发生变化时,可以直接读浏览器缓存的就不要向服务端发送请求。好比咱们ajax里面有一个参数可以设置请求的时候是否启用缓存,这种状况下就须要咱们在发送请求的时候作好相应的缓存处理。
(3)css文件放 在里面,js文件尽可能放在页面的底部。由于请求js文件是很花费时间,若是放在里面,就会致使页面的 DOM树呈现须要等待js文件加载完成。这也就是为何不少网站的源码里面看到引用的文件放在最后的缘由。
(4)使用压缩的css和js文件。这个不用多说,网络流量小。
(5)若是条件容许,尽可能使用CDN的方式引用文件,这样就能减小网络流量。好比咱们经常使用的网站http://www.bootcdn.cn/。
(6)在写js和css的语法时,尽可能避免重复的css,尽可能减小js里面循环的次数,诸如此类。
二、后端优化:
(1)程序的优化:这是一个很大的话题,我这里就选几个常见的。好比减小代码的层级结构、避免循环嵌套、避免循环CURD数据库、优化算法等等。
(2)数据库的优化:(因为数据库优化不是本题重点,因此可选几个主要的来讲)好比启用数据库缓存、经常使用的字段建索引、尽可能避免大事务操做、避免select * 的写法、尽可能不用in和not in 这种耗性能的用法等等。
(3)服务器优化:(这个可做为可选项)负载均衡、Web服务器和数据库分离、UI和Service分离等等。

2、MVC路由理解?(家常便饭)
出现指数:五颗星
主要考点:此题主要考点是MVC路由的理解。
参考答案:
一、首先咱们要理解MVC中路由的做用:url Routing的做用是将浏览器的URL请求映射到特定的MVC控制器动做。
二、当咱们访问http://localhost:8080/Home/Index 这个地址的时候,请求首先被UrlRoutingModule截获,截获请求后,从Routes中获得与当前请求URL相符合的RouteData对象, 将RouteData对象和当前URL封装成一个RequestContext对象,而后从Requestcontext封装的RouteData中获得 Controller名字,根据Controller的名字,经过反射建立控制器对象,这个时候控制器才真正被激活,最后去执行控制器里面对应的 action。
3、谈谈你以为作的不错系统,大概介绍下用到了哪些技术?
出现指数:五颗星
主要考点:这是一道很是开放的面试题。博主遇到过好几家公司的面试官都问道了这个,博主以为他们是想经过这个问题快速了解面试者的技术水平。此题只要结合你最近项目用到的技术谈谈就行了。
参考答案:
就拿我以前作过的一个项目为例来简单说明一下吧。项目分为客户端和服务端,客户端分 为BS客户端和CS客户端,BS客户端采用MVC 5.0的框架,CS客户端是Winform项目,服务端使用WebApi统一提供服务接口,考虑之后可能还要扩展手机端,因此服务接口的参数和返回值使用 通用的Json格式来传递数据。
一、服务端采用的面向接口编程,咱们在软件架构的过程当中,层和层之间经过接口依赖, 下层不是直接给上层提供实现,而是提供接口,具体的实现以依赖注入的方式在运行的时候动态注入进去。MEF就是实现依赖注入的一种组件。它的使用使得UI 层不直接依赖于BLL层,而是依赖于中间的一个IBLL层,在程序运行的时候,经过MEF动态将BLL里面的实现注入到UI层里面去,这样作的好处是减小 了层与层之间的耦合。服务端的异常里面、权限验证、日志记录等通用功能使用了AOP拦截的机制统一管理,项目中使用的是Postsharp这个组件,很好 地将通用需求功能从不相关的类当中分离出来,提升了代码的可维护性。
二、BS的客户端采用的jquery+bootstrap 的方式,全部页面采用流式布局,能更好适应各类不一样的终端设备(PC、手机)。项目中使用了各类功能强大的bootstrap组件,能适应各类复杂的业务需求。
4、Js继承实现。
出现指数:五颗星
主要考点:这道题考验面试者对js理解的深度。根据博主的经历,这种题通常在笔试出现的概率较大,为何把它放在这里,由于它确实太常见了。其实js实现继承的方式不少,咱们只要写好其中一种就行了。
参考答案:原型链继承

1 //1.定义Persiong函数 2 function Person(name, age) { 3 this.name = name; 4 this.age = age; 5 } 6 //2.经过原型链给Person添加一个方法 7 Person.prototype.getInfo = function () { 8 console.log(this.name + " is " + this.age + " years old!"); 9 }10 function Teacher(staffId) {11 this.staffId = staffId;12 }13 //3.经过prototype生命 Teacher继承Person14 Teacher.prototype = new Person();15 //4.实例Teacher函数16 var will = new Teacher(1000);17 will.name= "Will";18 will.age = 28;19 //5.调用父类函数20 will.getInfo();

5、谈谈你对设计模式的认识?结合你用得最多的一种设计模式说说它的使用。
出现指数:五颗星
主要考点:不用多说,这题考的就是对设计模式的理解。通常为了简单可能会要求你写一个单例模式,注意最好是写一个完整点的,考虑线程安全的那种。而后会让你说说你在项目中什么状况下会用到这种模式
参考答案:
通用写法

1 public class Singleton 2 { 3 // 定义一个静态变量来保存类的实例 4 private static Singleton uniqueInstance; 5 // 定义一个标识确保线程同步 6 private static readonly object locker = new object(); 7 // 定义私有构造函数,使外界不能建立该类实例 8 private Singleton() 9 {10 }11 ///

12 /// 定义公有方法提供一个全局访问点,同时你也能够定义公有属性来提供全局访问点13 /// 14 /// 15 public static Singleton GetInstance()16 {// 双重锁定只须要一句判断就能够了17 if (uniqueInstance == null)18 {19 lock (locker)20 {21 // 若是类的实例不存在则建立,不然直接返回22 if (uniqueInstance == null)23 {24 uniqueInstance = new Singleton();25 }26 }27 }28 return uniqueInstance;29 }30 }

单例模式确保一个类只有一个实例,并提供一个全局访问点,它的使用场景好比任务管理 器整个系统中应该只有一个把,再好比操做文件的对象,同一时间咱们只能有一个对象做文件吧。最重要的,好比咱们项目中用得很是多的功能→日志记录,在 一个线程中,记录日志的对象应该也只能有一个吧。单例模式的目的是为了保证程序的安全性和数据的惟一性。或者你也能够结合你使用的其余设计模式来讲明。
 
6、IIS的工做原理?
出现指数:四颗星
主要考点:此题主要考的是.net framework和IIS是如何结合呈现页面的。这是一个有点复杂的过程,面试的时候不可能说得完整,那么咱们就抓住几个关键点说说就能够。其实博主也不能彻底理解这个过程,今天正好借这个机会温
下。
参考答案:
一、当客户端发送HTTP Request时,服务端的HTTP.sys(能够理解为IIS的一个监听组件) 拦截到这个请求;
二、HTTP.sys 联系 WAS 向配置存储中心请求配置信息。
三、而后将请求传入IIS的应用程序池。
四、检查请求的后缀,启动aspnet_isapi.dll这个dll,这个dll是.net framework里面的,也就是说到这一步,请求进入了.net framework的管辖范围。
五、这个时候若是是WebForm,开始执行复杂的页面生命周期(HttpRuntime→ProcessRequest→HttpContext→HttpHandler);若是是MVC,则启动mvc的路由机制,根据路由规则为URL来指定HttpHandler。
六、httpHandler处理请求后,请求结束,给出Response,客户端处理响应,整个过程结束。

7、Http协议
出现指数:四颗星
主要考点:此题主要考对于web里面http协议的理解。
参考答案:
一、http协议是浏览器和服务器双方共同遵循的规范,是一种基于TCP/IP应用层协议。
二、http是一种典型的请求/响应协议。客户端发送请求,请求的内容以及参数存放到请求报文里面,服务端收到请求后,作出响应,返回响应的结果放到响应报文里面。经过F12能够查看请求报文和响应报文。
三、http协议是”无状态”的,当客户端向服务端发送一次http请求后,服务端收到请求而后返回给客户端相应的结果,服务器会当即断开链接并释放资源。在实际开发过程当中,咱们有时须要“保持”这种状态,因此衍生出了Session/Cookie这些技术。
四、http请求的方式主要有get/post。
五、http状态码最好记几个,博主有一次面试就被问到了。200(请求成功)、404(请求的资源不存在)、403(禁止访问)、5xx(服务端错误)

9、关于代码优化你怎么理解?你会考虑去代码重构吗?
出现指数:四颗星
主要考点:此题考的是面试者对代码优化的理解,以及代码如何重构的相关知识。
参考答案:
一、对于代码优化,以前的公司每周会作代码审核,审核的主要做用就是保证代码的正确性和执行效率,好比减小代码的层级结构、避免循环嵌套、避免循环CURD数据库、尽可能避免一次取出大量数据放在内存中(容易内存溢出)、优化算法等。
二、对于陈旧代码,可能不少地方有调用,而且开发和维护人员颇有可能不是同一我的,因此重构时要格外当心,若是没有十足的把握,不要轻易重构。若是必需要重构,必须作好充分的单元测试和全局测试。

10、谈谈你的优势和缺点?
出现指数:四颗星
主要考点:这道题让人有一种骂人的冲动,可是没办法,恰恰不少所谓的大公司会问这个。好比华为。这个问题见仁见智,答案能够本身组织。
参考答案:
优势:对于新的技术学**能力强,能很快适应新环境等等
缺点:对技术太过于执着等等

11、关于服务器端 MVC 架构的技术实现,您是怎样理解的?这种架构方式有什么好处?您在项目中是如何应用这一架构的?
出现指数:三颗星
主要考点:此题主要考的对于MVC这种框架的理解。
参考答案:MVC,顾名思义,Model、View、Controller。全部的 界面代码放在View里面,全部涉及和界面交互以及URL路由相关的逻辑都在Controller里面,Model提供数据模型。MVC的架构方式会让系 统的可维护性更高,使得每一部分更加专一本身的职责,而且MVC提供了强大的路由机制,方便了页面切换和界面交互。而后能够结合和WebForm的比较, 谈谈MVC如何解决复杂的控件树生成、如何避免了复杂的页面生命周期。
12、网站优化:网站运行慢,如何定位问题?发现问题如何解决?
出现指数:三颗星
主要考点:此题和问题一相似,考察Web的问题定位能力和优化方案。
参考答案:
浏览器F12→网络→查看http请求数以及每一个请求的耗时,找到问题的根源,而后依次解决,解决方案能够参考问题一里面的Web优化方案。

十3、说说你最擅长的技术?并说说你是如何使用的?
出现指数:三颗星
主要考点:这是一道很是开放的面试题。最初遇到这种问题,博主很想来一句:你妹,这叫什么问题!但确实有面试官问到。回头想一想,其实此题考查你擅长的技术的涉及深度。其实博主以为对于这个问题,能够结合你项目中用到的某一个技术来讲就行了。
参考答案:
简单谈谈MEF在咱们项目里面的使用吧。
在谈MEF以前,咱们必需要先谈谈DIP、IOC、DI
依赖倒置原则(DIP):一种软件架构设计的原则(抽象概念)
控制反转(IoC):一种反转流、依赖和接口的方式(DIP的具体实现方式)。
依赖注入(DI):IoC的一种实现方式,用来反转依赖(IoC的具体实现方式)。
什么意思呢?也就是说,咱们在软件架构的过程当中,层和层之间经过接口依赖,下层不是 直接给上层提供实现,而是提供接口,具体的实现以依赖注入的方式在运行的时候动态注入进去。MEF就是实现依赖注入的一种组件。它的使用使得UI层不直接 依赖于BLL层,而是依赖于中间的一个IBLL层,在程序运行的时候,经过MEF动态将BLL里面的实现注入到UI层里面去,这样作的好处是减小了层与层 之间的耦合。这也正是面向接口编程方式的体现。

十4、本身写过JS组件吗?举例说明。
出现指数:三颗星
主要考点:此题考的js组件封装和js闭包的一些用法。通常来讲,仍是笔试出现的概率较大。
参考答案:自定义html的select组件

1 //combobox 2 (function ($) { 3 $.fn.combobox = function (options, param) { 4 if (typeof options == 'string') { 5 return $.fn.combobox.methods[options](this, param); 6 } 7 options = .fn.combobox.defaults, options || {}); 8 var target = $(this); 9 target.attr('valuefield', options.valueField);10 target.attr('textfield', options.textField);11 target.empty();12 var option = $('');13 option.attr('value', '');14 option.text(options.placeholder);15 target.append(option);16 if (options.data) {17 init(target, options.data);18 }19 else {20 //var param = {};21 options.onBeforeLoad.call(target, option.param);22 if (!options.url) return;23 $.getJSON(options.url, option.param, function (data) {24 init(target, data);25 });26 }27 28 function init(target, data) {29 $.each(data, function (i, item) {30 var option = $('');31 option.attr('value', item[options.valueField]);32 option.text(item[options.textField]);33 target.append(option);34 });35 options.onLoadSuccess.call(target);36 }37 target.unbind("change"); target.on("change", function (e) { if (options.onChange) return options.onChange(target.val()); }); } $.fn.combobox.methods = { getValue: function (jq) { return jq.val(); }, setValue: function (jq, param) { jq.val(param); }, load: function (jq, url) { (''); option.attr('value', ''); option.text('请选择'); jq.append(option); (''); option.attr('value', item[jq.attr('valuefield')]); option.text(item[jq.attr('textfield')]); jq.append(option); }); }); } }; $.fn.combobox.defaults = { url: null, param: null, data: null, valueField: 'value', textField: 'text', placeholder: '请选择', onBeforeLoad: function (param) { }, onLoadSuccess: function () { }, onChange: function (value) { }38 };39 })(jQuery);

调用的时候
1 $("#sel_search_orderstatus").combobox({2 url: '/apiaction/Order/OrderApi/GetOrderStatu',3 valueField: 'VALUE',4 textField: 'NAME'5 });
就能自动从后台取数据,注意valueField和textField对应要显示和实际值。

十5、本身写过多线程组件吗?简要说明!
出现指数:三颗星
主要考点:此题是两年前博主在携程的一次电话面试中遇到的,其余地方基本上没遇到过,其实到如今也不能理解当时面试官问这个问题的目的。但我想,此问题必有出处,估计面试官是想了解你对多线程以及线程池等的理解深度。
知识点:
一、什么是面向对象?
面向对象说到底就是一种思想,任何事物均可以看做是一个对象。在有些面试题目中也称之为OOP(Object Oriented Programming)。分开来解读就是:
Object:对象
Oriented: 面向的
Programming:程序设计
面向对象就是把一我的或事务的属性,好比名字,年龄这些定义在一个实体类里面。存和取的时候直接使用存取实体类就把这我的的名字,年龄这些所有存了,这个实体类就叫对象,这种思想就叫面向对象。
面向对象开发具备如下优势:
    代码开发模块化,便于维护。
    代码复用性强
    代码的可靠性和灵活性。
    代码的可读性和可扩展性。

3 .列举ASP.NET 页面之间传递值的几种方式。
答. 1.Request.QueryString
    2.Request.Form
    3.Session
    4.Application
    5.Cache
    6.Cookie
    7.Server.Transfer
    8.Database
    9.HttpContext的Item属性等

4.a=10,b=15,请在不使用第三方变量的状况下,把a、b的值互换
答: int a=a+b; int b=a-b;int a=a-b;

5.用.net作B/S结构的系统,您是用几层结构来开发,每一层之间的关系以及为何要这样分层?
答:通常为3层:数据访问层,业务层,表示层。
数据访问层对数据库进行增删查改。
业务层通常分为二层,业务表观层实现与表示层的沟通,业务规则层实现用户密码的安全等。
表示层为了与用户交互例如用户添加表单。
优势: 分工明确,条理清晰,易于调试,并且具备可扩展性。
缺点: 增长成本。

6.能用foreach遍历访问的对象须要实现 ________________接口或声明________________方法的类型。
答:IEnumerable 、 GetEnumerator。

7.GC是什么? 为何要有GC?
答:GC是垃圾收集器。程序员不用担忧内存管理,由于垃圾收集器会自动进行管理。要请求垃圾收集,能够调用下面的方法之一:
       System.gc()
       Runtime.getRuntime().gc()

8.启动一个线程是用run()仍是start()?
答:启动一个线程是调用start()方法,使线程所表明的虚拟处理机处于可运行状态,这意味着它能够由JVM调度并执行。这并不意味着线程就会当即运行。run() 方法能够产生必须退出的标志来中止一个线程。

9.是否能够继承String类?
答:String类是final类故不能够继承。

10.session喜欢丢值且占内存,Cookis不安全,请问用什么办法代替这两种原始的方法
答:redis 或者 memcache。固然,微软也提供了解决方案。iis中因为有进程回收机制,系统繁忙的话Session会丢失,能够用Sate server或SQL Server数据库的方式。

11.IOC容器?

  1. IOC即控制反转,是一种设计思想,在以前的项目中,当咱们须要一个对象时,须要new一个对象,而IOC的设计思想是咱们将须要的对象注入到一个容器中,就会得到咱们所须要的资源 。
  2. IOC和DI IOC是控制反转,DI是依赖注入,控制反转的解释有些模棱两可,而依赖注入就很明确,咱们将须要的对象注入到容器中,获取所须要的资源。
  3. IOC控制反转:正常状况下程序开发是上端调用下端,依赖下端,依赖倒置原则告诉咱们,上端不要依赖下端,要依赖抽象,上端只依赖抽象,细节交给第三方工厂(容器)来决定,这就是IOC,就是控制反转——使系统架构能够更稳定,支持扩展。

十二、什么是委托,事件是否是一种委托?

  1. 委托能够把一个方法做为参数代入另外一个方法。
  2. 委托能够理解为指向一个函数的引用。
  3. 事件是一种特殊的委托。
    delegate <函数返回类型> <委托名> (<函数参数>)

13.c#多线程是什么?
多线程的优势:能够同时完成多个任务;能够使程序的响应速度更快;能够节省大量时间进行处理任务;能够随时中止任务;能够设置每一个任务的优先级,以优化程序性能。

14.WebApi概述
Web API是在.NET Framework之上构建的Web的API的框架,Web API是一个编程接口,用于操做可经过标准HTTP方法和标头访问的系统,Web API须要基于.NET 3.5或更高版本才能够进行开发

15.什么是WebService
webservice是一种跨平台,跨语言的规范,用于不一样平台,不一样语言开发的应用之间的交互,是基于网络的、分布式的模块化组件,它执行特定的任务,遵照具体的技术规范。

16.存储过程是什么?有什么用?有什么优势?用什么来调用?
存储过程是预编译,安全性高,也是大大提升了效率,存储过程能够重复使用以减小数据库开发人员的工做量,复杂的逻辑咱们能够使用存储过程完成,在存储过程当中咱们能够使用临时表,还能够定义变量,拼接sql语句,调用时,只需执行这个存储过程名,传入咱们所须要的参数便可。
17.何为触发器?
触发器是一种特殊的存储过程,主要是经过事件触发而被执行。它能够强化约束来维护数据的完整性和一致性,能够跟踪数据库内的操做从而不容许未经许可的更新和变化。能够级联运算。
常见的触发器有三种:分别应用于Insert , Update , Delete 事件。

18.什么叫作泛型?
只是为了去掉重复代码,应对不一样类型的共同需求。

  1. C#中值类型和引用类型分别有哪些? 
    值类型:结构体(数值类型,bool型,用户定义的结构体),枚举,可空类型。
    引用类型:数组,用户定义的类、接口、委托,object,字符串。

21 .NET的错误处理机制是什么?
.net错误处理机制采用try->catch->finally结构,发生错误时,层层上抛,直到找到匹配的Catch为止。

22.C#能否对内存进行直接的操做?
在.net下,.net引用了垃圾回收(GC)功能,它替代了程序员不过在C#中,不能直接实现Finalize方法,而是在析构函数中调用基类的Finalize()方法。

  1. ADO.NET相对于ADO等主要有什么改进?
    1:ado.net不依赖于ole db提供程序,而是使用.net托管提供的程序,
    2:不使用com
    3:不在支持动态游标和服务器端游
    4:,能够断开connection而保留当前数据集可用
    5:强类型转换
    6:xml支持

24.若是在一个B/S结构的系统中须要传递变量值,可是又不能使用Session、Cookie、Application,您有几种方法进行处理?
this.Server.Transfer、Response.Redirect()、QueryString

  1. .NET中读写数据库须要用到那些类?他们的做用?
    Connection链接对象,Command执行命令和存储过程,DataReader向前只读的数据流,DataAdapter适配器,支持增删查询,DataSet数据级对象,至关与内存里的一张或多张表。

26.简要谈一下您对微软.NET架构下remoting和webservice两项技术的理解以及实际中的应用。
WS主要是可利用HTTP,穿透防火墙。而Remoting能够利用TCP/IP,二进制传送提升效率。
remoting是.net中用来跨越machine,process, appdomain进行方法调用的技术,对于三成结构的程序,就能够使用remoting技术来构建.它是分布应用的基础技术.至关于之前的DCOM。
Web Service是一种构建应用程序的普通模型,并能在全部支持internet网通信的操做系统上实施。Web Service令基于组件的开发和web的结合达到最佳,基于组件的对象模型。

27.什么是反射?
动态获取程序集信息。

28.override与重载的区别?
重载是方法的名称相同。参数或参数类型不一样,进行屡次重载以适应不一样的须要。
Override是子类对基类中函数的重写。为了适应须要。

29.装箱和拆箱的概念和原理
装箱是将值类型转化为引用类型的过程;
拆箱是将引用类型转化为值类型的过程

30.Session有什么重大BUG,微软提出了什么方法加以解决?
是iis中因为有进程回收机制,系统繁忙的话Session会丢失,能够用Sate server或SQL Server数据库的方式存储Session不过这种方式比较慢,并且没法捕获Session的END事件。
 
参考文献:https://blog.csdn.net/user2041/article/details/80591365
特性一:正则表达式
相信你们都会很是喜欢这个特性,无须服务器端的检测,使用浏览器的本地功能就能够帮助你判断电子邮件的格式,URL,或者是电话格式,防止用户输入错误的信息,经过使用HTML5的pattern属性,咱们能够很方便的整合这个功能,代码以下:

运行以下:
若是在Firefox浏览器中运行,而且输入错误的email地址,会看到以下:
特性二:数据列表元素
在没有HTML5的日子里,咱们会选择使用一些JS或者知名的jQuery UI来实现自动补齐的功能,而在HTML5中,咱们能够直接使用datalist元素,以下:

运行代码: 若是你输入字母“j",能够看到以下的自动补齐效果: 特性三:下载属性 HTML5的下载属性能够容许开发者强制下载一个页面,而非加载那个页面,这样的话,你不须要实现服务器端的一些功能来达到一样的效果,是否是很是贴心? 下载PDF文件 特性四:DNS的预先加载处理 要知道DNS的的解析成本很高滴,每每致使了网站加载速度慢。如今浏览器针对这个问题开发了更智能的处理方式,它将域名缓存后,当用户点击其它页面地址后自动的获取。 若是你但愿预先获取NDS,你能够控制你的浏览器来解析域名,例如: 特性五:连接网页的预先加载处理 要知道连接可以在也页面中帮助用户导航,可是页面加载的速度快慢决定了用户体验的好与坏,使用以下HTML5的prefetch属性能够帮助你针对指定的地址预加载页面或者页面中的特定资源,这样用户点击的时候,会发现页面加载速度提升了。 或者能够使用prerender属性,这个属性可以帮助你提早加载整个页面,以下: 经过设置这个属性,登陆极客社区后,极客搜索页面已经加载了,这样若是你须要搜索,页面会马上加载,相信你的用户确定喜欢访问这样的网站!

摘要:计算机网络基础
引言
网络协议是每一个前端工程师都必需要掌握的知识,TCP/IP 中有两个具备表明性的传输层协议,分别是 TCP 和 UDP,本文将介绍下这二者以及它们之间的区别。
1、TCP/IP网络模型
计算机与网络设备要相互通讯,双方就必须基于相同的方法。好比,如何探测到通讯目标、由哪一边先发起通讯、使用哪一种语言进行通讯、怎样结束通讯等规则都须要事先肯定。不一样的硬件、操做系统之间的通讯,全部的这一切都须要一种规则。而咱们就把这种规则称为协议(protocol)。
TCP/IP 是互联网相关的各种协议族的总称,好比:TCP,UDP,IP,FTP,HTTP,ICMP,SMTP 等都属于 TCP/IP 族内的协议。
TCP/IP模型是互联网的基础,它是一系列网络协议的总称。这些协议能够划分为四层,分别为链路层、网络层、传输层和应用层。
链路层:负责封装和解封装IP报文,发送和接受ARP/RARP报文等。
网络层:负责路由以及把分组报文发送给目标网络或主机。
传输层:负责对报文进行分组和重组,并以TCP或UDP协议格式封装报文。
应用层:负责向用户提供应用程序,好比HTTP、FTP、Telnet、DNS、SMTP等。

在网络体系结构中网络通讯的创建必须是在通讯双方的对等层进行,不能交错。 在整个数据传输过程当中,数据在发送端时通过各层时都要附加上相应层的协议头和协议尾(仅数据链路层须要封装协议尾)部分,也就是要对数据进行协议封装,以标识对应层所用的通讯协议。接下去介绍TCP/IP 中有两个具备表明性的传输层协议----TCP和UDP。
2、UDP
UDP协议全称是用户数据报协议,在网络中它与TCP协议同样用于处理数据包,是一种无链接的协议。在OSI模型中,在第四层——传输层,处于IP协议的上一层。UDP有不提供数据包分组、组装和不能对数据包进行排序的缺点,也就是说,当报文发送以后,是没法得知其是否安全完整到达的。
它有如下几个特色:

  1. 面向无链接
    首先 UDP 是不须要和 TCP同样在发送数据前进行三次握手创建链接的,想发数据就能够开始发送了。而且也只是数据报文的搬运工,不会对数据报文进行任何拆分和拼接操做。
    具体来讲就是:
    在发送端,应用层将数据传递给传输层的 UDP 协议,UDP 只会给数据增长一个 UDP 头标识下是 UDP 协议,而后就传递给网络层了
    在接收端,网络层将数据传递给传输层,UDP 只去除 IP 报文头就传递给应用层,不会任何拼接操做
  2. 有单播,多播,广播的功能
    UDP 不止支持一对一的传输方式,一样支持一对多,多对多,多对一的方式,也就是说 UDP 提供了单播,多播,广播的功能。
  3. UDP是面向报文的
    发送方的UDP对应用程序交下来的报文,在添加首部后就向下交付IP层。UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界。所以,应用程序必须选择合适大小的报文
  4. 不可靠性
    首先不可靠性体如今无链接上,通讯都不须要创建链接,想发就发,这样的状况确定不可靠。
    而且收到什么数据就传递什么数据,而且也不会备份数据,发送数据也不会关心对方是否已经正确接收到数据了。
    再者网络环境时好时坏,可是 UDP 由于没有拥塞控制,一直会以恒定的速度发送数据。即便网络条件很差,也不会对发送速率进行调整。这样实现的弊端就是在网络条件很差的状况下可能会致使丢包,可是优势也很明显,在某些实时性要求高的场景(好比电话会议)就须要使用 UDP 而不是 TCP。

从上面的动态图能够得知,UDP只会把想发的数据报文一股脑的丢给对方,并不在乎数据有无安全完整到达。
5. 头部开销小,传输数据报文时是很高效的。

UDP 头部包含了如下几个数据:
两个十六位的端口号,分别为源端口(可选字段)和目标端口
整个数据报文的长度
整个数据报文的检验和(IPv4 可选 字段),该字段用于发现头部信息和数据中的错误
所以 UDP 的头部开销小,只有八字节,相比 TCP 的至少二十字节要少得多,在传输数据报文时是很高效的
3、TCP
当一台计算机想要与另外一台计算机通信时,两台计算机之间的通讯须要畅通且可靠,这样才能保证正确收发数据。例如,当你想查看网页或查看电子邮件时,但愿完整且按顺序查看网页,而不丢失任何内容。当你下载文件时,但愿得到的是完整的文件,而不只仅是文件的一部分,由于若是数据丢失或乱序,都不是你但愿获得的结果,因而就用到了TCP。
TCP协议全称是传输控制协议是一种面向链接的、可靠的、基于字节流的传输层通讯协议,由 IETF 的RFC 793定义。TCP 是面向链接的、可靠的流协议。流就是指不间断的数据结构,你能够把它想象成排水管中的水流。

  1. TCP链接过程
    以下图所示,能够看到创建一个TCP链接的过程为(三次握手的过程):

第一次握手
客户端向服务端发送链接请求报文段。该报文段中包含自身的数据通信初始序号。请求发送后,客户端便进入 SYN-SENT 状态。
第二次握手
服务端收到链接请求报文段后,若是赞成链接,则会发送一个应答,该应答中也会包含自身的数据通信初始序号,发送完成后便进入 SYN-RECEIVED 状态。
第三次握手
当客户端收到链接赞成的应答后,还要向服务端发送一个确认报文。客户端发完这个报文段后便进入 ESTABLISHED 状态,服务端收到这个应答后也进入 ESTABLISHED 状态,此时链接创建成功。
这里可能你们会有个疑惑:为何 TCP 创建链接须要三次握手,而不是两次?这是由于这是为了防止出现失效的链接请求报文段被服务端接收的状况,从而产生错误。

  1. TCP断开连接

TCP 是全双工的,在断开链接时两端都须要发送 FIN 和 ACK。
第一次握手
若客户端 A 认为数据发送完成,则它须要向服务端 B 发送链接释放请求。
第二次握手
B 收到链接释放请求后,会告诉应用层要释放 TCP 连接。而后会发送 ACK 包,并进入 CLOSE_WAIT 状态,此时代表 A 到 B 的链接已经释放,再也不接收 A 发的数据了。可是由于 TCP 链接是双向的,因此 B 仍旧能够发送数据给 A。
第三次握手
B 若是此时还有没发完的数据会继续发送,完毕后会向 A 发送链接释放请求,而后 B 便进入 LAST-ACK 状态。
第四次握手
A 收到释放请求后,向 B 发送确认应答,此时 A 进入 TIME-WAIT 状态。该状态会持续 2MSL(最大段生存期,指报文段在网络中生存的时间,超时会被抛弃) 时间,若该时间段内没有 B 的重发请求的话,就进入 CLOSED 状态。当 B 收到确认应答后,也便进入 CLOSED 状态。
3. TCP协议的特色

面向链接

面向链接,是指发送数据以前必须在两端创建链接。创建链接的方法是“三次握手”,这样能创建可靠的链接。创建链接,是为数据的可靠传输打下了基础。


仅支持单播传输

每条TCP传输链接只能有两个端点,只能进行点对点的数据传输,不支持多播和广播传输方式。
面向字节流
TCP不像UDP同样那样一个个报文独立地传输,而是在不保留报文边界的状况下以字节流方式进行传输。

可靠传输

对于可靠传输,判断丢包,误码靠的是TCP的段编号以及确认号。TCP为了保证报文传输的可靠,就给每一个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。而后接收端实体对已成功收到的字节发回一个相应的确认(ACK);若是发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据(假设丢失了)将会被重传。


提供拥塞控制

当网络出现拥塞的时候,TCP可以减少向网络注入数据的速率和数量,缓解拥塞
TCP提供全双工通讯
TCP容许通讯双方的应用程序在任什么时候候都能发送数据,由于TCP链接的两端都设有缓存,用来临时存放双向通讯的数据。固然,TCP能够当即发送一个数据段,也能够缓存一段时间以便一次发送更多的数据段(最大的数据段大小取决于MSS)
4、TCP和UDP的比较

  1. 对比
    UDP TCP
    是否链接 无链接 面向链接
    是否可靠 不可靠传输,不使用流量控制和拥塞控制 可靠传输,使用流量控制和拥塞控制
    链接对象个数 支持一对一,一对多,多对一和多对多交互通讯 只能是一对一通讯
    传输方式 面向报文 面向字节流
    首部开销 首部开销小,仅8字节 首部最小20字节,最大60字节
    适用场景 适用于实时应用(IP电话、视频会议、直播等) 适用于要求可靠传输的应用,例如文件传输
  2. 总结
    TCP向上层提供面向链接的可靠服务 ,UDP向上层提供无链接不可靠服务。
    虽然 UDP 并无 TCP 传输来的准确,可是也能在不少实时性要求高的地方有所做为
    对数据准确性要求高,速度能够相对较慢的,能够选用TCP
    参考文章与书籍

基础篇
怎样建立一个线程
受托管的线程与 Windows线程
前台线程与后台线程
名为BeginXXX和EndXXX的方法是作什么用的
异步和多线程有什么关联
WinForm多线程编程篇
个人多线程WinForm程序总是抛出InvalidOperationException ,怎么解决?
Invoke,BeginInvoke干什么用的,内部是怎么实现的
每一个线程都有消息队列吗?
为何Winform不容许跨线程修改UI线程控件的值
有没有什么办法能够简化WinForm多线程的开发
线程池
线程池的做用是什么?
全部进程使用一个共享的线程池,仍是每一个进程使用独立的线程池?
为何不要手动线程池设置最大值?
.Net线程池有什么不足?
同步
CLR怎样实现lock(obj)锁定?
WaitHandle是什么,他和他的派生类怎么使用
什么是用双锁实现Singleton,为何要这样作,为何有人说双锁检验是不安全的
互斥对象(Mutex)、事件(Event)对象与lock语句的比较
何时须要锁定
只有共享资源才须要锁定
把锁定交给数据库
了解你的程序是怎么运行的
业务逻辑对事务和线程安全的要求
计算一下冲突的可能性
请多使用lock,少用Mutex
Web和IIS
应用程序池,WebApplication,和线程池之间有什么关系
Web页面怎么调用异步WebService
 
基础篇
 
 怎样建立一个线程
我只简单列举几种经常使用的方法,详细可参考.Net多线程总结(一)
一)使用Thread类
ThreadStart threadStart=new ThreadStart(Calculate);//经过ThreadStart委托告诉子线程讲执行什么方法,这里执行一个计算圆周长的方法
Thread thread=new Thread(threadStart);
thread.Start(); //启动新线程

public void Calculate(){
double Diameter=0.5;
Console.Write("The perimeter Of Circle with a Diameter of {0} is {1}"Diameter,Diameter*Math.PI);
}
 
二)使用Delegate.BeginInvoke
delegate double CalculateMethod(double Diameter); //申明一个委托,代表须要在子线程上执行的方法的函数签名
static CalculateMethod calcMethod = new CalculateMethod(Calculate);//把委托和具体的方法关联起来
static void Main(string[] args)
{
//此处开始异步执行,而且能够给出一个回调函数(若是不须要执行什么后续操做也能够不使用回调)
calcMethod.BeginInvoke(5, new AsyncCallback(TaskFinished), null);
Console.ReadLine();
}

//线程调用的函数,给出直径做为参数,计算周长
public static double Calculate(double Diameter)
{
    return Diameter * Math.PI;
}

//线程完成以后回调的函数
public static void TaskFinished(IAsyncResult result)
{
    double re = 0;
    re = calcMethod.EndInvoke(result);
    Console.WriteLine(re);
}

三)使用ThreadPool.QueueworkItem
WaitCallback w = new WaitCallback(Calculate);
//下面启动四个线程,计算四个直径下的圆周长
ThreadPool.QueueUserWorkItem(w, 1.0);
ThreadPool.QueueUserWorkItem(w, 2.0);
ThreadPool.QueueUserWorkItem(w, 3.0);
ThreadPool.QueueUserWorkItem(w, 4.0);
public static void Calculate(double Diameter)
{
return Diameter * Math.PI;
}
 
下面两条来自于http://www.cnblogs.com/tonyman/archive/2007/09/13/891912.html
  受托管的线程与 Windows线程
必需要了解,执行.NET应用的线程实际上仍然是Windows线程。可是,当某个线程被CLR所知时,咱们将它称为受托管的线程。具体来讲,由受托管的代码建立出来的线程就是受托管的线程。若是一个线程由非托管的代码所建立,那么它就是非托管的线程。不过,一旦该线程执行了受托管的代码它就变成了受托管的线程。
一个受托管的线程和非托管的线程的区别在于,CLR将建立一个System.Threading.Thread类的实例来表明并操做前者。在内部实现中,CLR将一个包含了全部受托管线程的列表保存在一个叫作ThreadStore地方。
CLR确保每个受托管的线程在任意时刻都在一个AppDomain中执行,可是这并不表明一个线程将永远处在一个AppDomain中,它能够随着时间的推移转到其余的AppDomain中。
从安全的角度来看,一个受托管的线程的主用户与底层的非托管线程中的Windows主用户是无关的。
 
  前台线程与后台线程

启动了多个线程的程序在关闭的时候却出现了问题,若是程序退出的时候不关闭线程,那么线程就会一直的存在,可是大多启动的线程都是局部变量,不能一一的关闭,若是调用Thread.CurrentThread.Abort()方法关闭主线程的话,就会出现ThreadAbortException 异常,所以这样不行。
后来找到了这个办法: Thread.IsBackground 设置线程为后台线程。
 
msdn对前台线程和后台线程的解释:托管线程或者是后台线程,或者是前台线程。后台线程不会使托管执行环境处于活动状态,除此以外,后台线程与前台线程是同样的。一旦全部前台线程在托管进程(其中 .exe 文件是托管程序集)中被中止,系统将中止全部后台线程并关闭。经过设置 Thread.IsBackground 属性,能够将一个线程指定为后台线程或前台线程。例如,经过将 Thread.IsBackground 设置为 true,就能够将线程指定为后台线程。一样,经过将 IsBackground 设置为 false,就能够将线程指定为前台线程。从非托管代码进入托管执行环境的全部线程都被标记为后台线程。经过建立并启动新的 Thread 对象而生成的全部线程都是前台线程。若是要建立但愿用来侦听某些活动(如套接字链接)的前台线程,则应将 Thread.IsBackground 设置为 true,以便进程能够终止。
因此解决办法就是在主线程初始化的时候,设置:Thread.CurrentThread.IsBackground = true;

这样,主线程就是后台线程,在关闭主程序的时候就会关闭主线程,从而关闭全部线程。可是这样的话,就会强制关闭全部正在执行的线程,因此在关闭的时候要对线程工做的结果保存。

常常看到名为BeginXXX和EndXXX的方法,他们是作什么用的
这是.net的一个异步方法名称规范
.Net在设计的时候为异步编程设计了一个异步编程模型(APM),这个模型不只是使用.NET的开发人员使用,.Net内部也频繁用到,好比全部的Stream就有BeginRead,EndRead,Socket,WebRequet,SqlCommand都运用到了这个模式,通常来说,调用BegionXXX的时候,通常会启动一个异步过程去执行一个操做,EndEnvoke能够接收这个异步操做的返回,固然若是异步操做在EndEnvoke调用的时候尚未执行完成,EndInvoke会一直等待异步操做完成或者超时
.Net的异步编程模型(APM)通常包含BeginXXX,EndXXX,IAsyncResult这三个元素,BeginXXX方法都要返回一个IAsyncResult,而EndXXX都须要接收一个IAsyncResult做为参数,他们的函数签名模式以下
IAsyncResult BeginXXX(...);
<返回类型> EndXXX(IAsyncResult ar);
BeginXXX和EndXXX中的XXX,通常都对应一个同步的方法,好比FileStream的Read方法是一个同步方法,相应的BeginRead(),EndRead()就是他的异步版本,HttpRequest有GetResponse来同步接收一个响应,也提供了BeginGetResponse和EndGetResponse这个异步版本,而IAsynResult是两者联系的纽带,只有把BeginXXX所返回的IAsyncResult传给对应的EndXXX,EndXXX才知道须要去接收哪一个BeginXXX发起的异步操做的返回值。
这个模式在实际使用时稍显繁琐,虽然原则上咱们能够随时调用EndInvoke来得到返回值,而且能够同步多个线程,可是大多数状况下当咱们不须要同步不少线程的时候使用回调是更好的选择,在这种状况下三个元素中的IAsynResult就显得多余,咱们一不须要用其中的线程完结标志来判断线程是否成功完成(回调的时候线程应该已经完成了),二不须要他来传递数据,由于数据能够写在任何变量里,而且回调时应该已经填充,因此能够看到微软在新的.Net Framework中已经增强了对回调事件的支持,这总模型下,典型的回调程序应该这样写
a.DoWork+=new SomeEventHandler(Caculate);
a.CallBack+=new SomeEventHandler(callback);
a.Run();
(注:我上面讲的是广泛的用法,然而BeginXXX,EndXXX仅仅是一种模式,而对这个模式的实现彻底取决于使用他的开发人员,具体实现的时候你能够使用另一个线程来实现异步,也可能使用硬件的支持来实现异步,甚至可能根本和异步没有关系(尽管几乎没有人会这样作)-----好比直接在Beginxxx里直接输出一个"Helloworld",若是是这种极端的状况,那么上面说的一切都是废话,因此上面的探讨并不涉及内部实现,只是告诉你们微软的模式,和框架中对这个模式的经典实现)

异步和多线程有什么关联
有一句话总结的很好:多线程是实现异步的一种手段和工具
咱们一般把多线程和异步等同起来,实际是一种误解,在实际实现的时候,异步有许多种实现方法,咱们能够用进程来作异步,或者使用纤程,或者硬件的一些特性,好比在实现异步IO的时候,能够有下面两个方案:
1)能够经过初始化一个子线程,而后在子线程里进行IO,而让主线程顺利往下执行,当子线程执行完毕就回调
2)也能够根本不使用新线程,而使用硬件的支持(如今许多硬件都有本身的处理器),来实现彻底的异步,这是咱们只须要将IO请求告知硬件驱动程序,而后迅速返回,而后等着硬件IO就绪通知咱们就能够了
实际上DotNet Framework里面就有这样的例子,当咱们使用文件流的时候,若是制定文件流属性为同步,则使用BeginRead进行读取时,就是用一个子线程来调用同步的Read方法,而若是指定其为异步,则一样操做时就使用了须要硬件和操做系统支持的所谓IOCP的机制

WinForm多线程编程篇
 
 
个人多线程WinForm程序总是抛出InvalidOperationException ,怎么解决?
在WinForm中使用多线程时,经常遇到一个问题,当在子线程(非UI线程)中修改一个控件的值:好比修改进度条进度,时会抛出以下错误
Cross-thread operation not valid: Control 'XXX' accessed from a thread other than the thread it was created on.
在VS2005或者更高版本中,只要不是在控件的建立线程(通常就是指UI主线程)上访问控件的属性就会抛出这个错误,解决方法就是利用控件提供的Invoke和BeginInvoke把调用封送回UI线程,也就是让控件属性修改在UI线程上执行,下面列出会报错的代码和他的修改版本

ThreadStart threadStart=new ThreadStart(Calculate);//经过ThreadStart委托告诉子线程讲执行什么方法
Thread thread=new Thread(threadStart);
thread.Start();
public void Calculate(){
    double Diameter=0.5;
    double result=Diameter*Math.PI;
    CalcFinished(result);//计算完成须要在一个文本框里显示
}
public void CalcFinished(double result){
    this.TextBox1.Text=result.ToString();//会抛出错误
}
上面加粗的地方在debug的时候会报错,最直接的修改方法是修改Calculate这个方法以下

delegate void changeText(double result);

public void Calculate(){
    double Diameter=0.5;
    double result=Diameter*Math.PI;
    this.BeginInvoke(new changeText(CalcFinished),t.Result);//计算完成须要在一个文本框里显示
}
这样就ok了,可是最漂亮的方法是不去修改Calculate,而去修改CalcFinished这个方法,由于程序里调用这个方法的地方可能不少,因为加了是否须要封送的判断,这样修改还能提升非跨线程调用时的性能

delegate void changeText(double result);

public void CalcFinished(double result){
    if(this.InvokeRequired){
        this.BeginInvoke(new changeText(CalcFinished),t.Result);
    }
    else{
        this.TextBox1.Text=result.ToString();
    }
}
上面的作法用到了Control的一个属性InvokeRequired(这个属性是能够在其余线程里访问的),这个属性代表调用是否来自另非UI线程,若是是,则使用BeginInvoke来调用这个函数,不然就直接调用,省去线程封送的过程

Invoke,BeginInvoke干什么用的,内部是怎么实现的?
这两个方法主要是让给出的方法在控件建立的线程上执行
Invoke使用了Win32API的SendMessage,
UnsafeNativeMethods.PostMessage(new HandleRef(this, this.Handle), threadCallbackMessage, IntPtr.Zero, IntPtr.Zero);
BeginInvoke使用了Win32API的PostMessage
UnsafeNativeMethods.PostMessage(new HandleRef(this, this.Handle), threadCallbackMessage, IntPtr.Zero, IntPtr.Zero);
这两个方法向UI线程的消息队列中放入一个消息,当UI线程处理这个消息时,就会在本身的上下文中执行传入的方法,换句话说凡是使用BeginInvoke和Invoke调用的线程都是在UI主线程中执行的,因此若是这些方法里涉及一些静态变量,不用考虑加锁的问题

每一个线程都有消息队列吗?
不是,只有建立了窗体对象的线程才会有消息队列(下面给出<Windows 核心编程>关于这一段的描述)
当一个线程第一次被创建时,系统假定线程不会被用于任何与用户相关的任务。这样能够减小线程对系统资源的要求。可是,一旦这个线程调用一个与图形用户界面有关的函数(例如检查它的消息队列或创建一个窗口),系统就会为该线程分配一些另外的资源,以便它可以执行与用户界面有关的任务。特别是,系统分配一个T H R E A D I N F O结构,并将这个数据结构与线程联系起来。
这个T H R E A D I N F O结构包含一组成员变量,利用这组成员,线程能够认为它是在本身独占的环境中运行。T H R E A D I N F O是一个内部的、未公开的数据结构,用来指定线程的登记消息队列(posted-message queue)、发送消息队列( send-message queue)、应答消息队列( r e p l y -message queue)、虚拟输入队列(virtualized-input queue)、唤醒标志(wake flag)、以及用来描述线程局部输入状态的若干变量。图2 6 - 1描述了T H R E A D I N F O结构和与之相联系的三个线程。

为何Winform不容许跨线程修改UI线程控件的值
在vs2003下,使用子线程调用ui线程建立的控件的属性是不会有问题的,可是编译的时候会出现警告,可是vs2005及以上版本就会有这样的问题,下面是msdn上的描述
"当您在 Visual Studio 调试器中运行代码时,若是您从一个线程访问某个 UI 元素,而该线程不是建立该 UI 元素时所在的线程,则会引起 InvalidOperationException。调试器引起该异常以警告您存在危险的编程操做。UI 元素不是线程安全的,因此只应在建立它们的线程上进行访问"
从上面能够看出,这个异常实际是debugger耍的花招,也就是说,若是你直接运行程序的exe文件,或者利用运行而不调试(Ctrl+F5)来运行你的程序,是不会抛出这样的异常的.大概ms发现v2003的警告对广大开发者不起做用,因此用了一个比较狠一点的方法.
不过问题依然存在:既然这样设计的缘由主要是由于控件的值非线程安全,那么DotNet framework中非线程安全的类千千万万,为何恰恰跨线程修改Control的属性会有这样严格的限制策略呢?
这个问题我还回答很差,但愿博友们可以予以补充
 
有没有什么办法能够简化WinForm多线程的开发
使用backgroundworker,使用这个组建能够避免回调时的Invoke和BeginInvoke,而且提供了许多丰富的方法和事件
参见.Net多线程总结(二)-BackgroundWorker,我在这里再也不赘诉

线程池
 
线程池的做用是什么
做用是减少线程建立和销毁的开销
建立线程涉及用户模式和内核模式的切换,内存分配,dll通知等一系列过程,线程销毁的步骤也是开销很大的,因此若是应用程序使用了完一个线程,咱们能把线程暂时存放起来,以备下次使用,就能够减少这些开销
全部进程使用一个共享的线程池,仍是每一个进程使用独立的线程池?
每一个进程都有一个线程池,一个Process中只能有一个实例,它在各个应用程序域(AppDomain)是共享的,.Net2.0 中默认线程池的大小为工做线程25个,IO线程1000个,有一个比较广泛的误解是线程池中会有1000个线程等着你去取,其实否则, ThreadPool仅仅保留至关少的线程,保留的线程能够用SetMinThread这个方法来设置,当程序的某个地方须要建立一个线程来完成工做时,而线程池中又没有空闲线程时,线程池就会负责建立这个线程,而且在调用完毕后,不会马上销毁,而是把他放在池子里,预备下次使用,同时若是线程超过必定时间没有被使用,线程池将会回收线程,因此线程池里存在的线程数实际是个动态的过程
为何不要手动线程池设置最大值?
当我首次看到线程池的时候,脑壳里的第一个念头就是给他设定一个最大值,然而当咱们查看ThreadPool的SetMaxThreads文档时每每会看到一条警告:不要手动更改线程池的大小,这是为何呢?
其实不管FileStream的异步读写,异步发送接受Web请求,甚至使用delegate的beginInvoke都会默认调用 ThreadPool,也就是说不只你的代码可能使用到线程池,框架内部也可能使用到,更改的后果影响就很是大,特别在iis中,一个应用程序池中的全部 WebApplication会共享一个线程池,对最大值的设定会带来不少意想不到的麻烦
线程池的线程为什么要分类?
线程池有一个方法可让咱们看到线程池中可用的线程数量:GetAvaliableThread(out workerThreadCount,out iocompletedThreadCount),对于我来讲,第一次看到这个函数的参数时十分困惑,由于我指望这个函数直接返回一个整形,代表还剩多少线程,这个函数竟然一次返回了两个变量.
原来线程池里的线程按照公用被分红了两大类:工做线程和IO线程,或者IO完成线程,前者用于执行普通的操做,后者专用于异步IO,好比文件和网络请求,注意,分类并不说明两种线程自己有差异,线程就是线程,是一种执行单元,从本质上来说都是同样的,线程池这样分类,举例来讲,就好像某施工工地如今有1000把铁锹,规定其中25把给后勤部门用,其余都给施工部门,施工部门须要大量使用铁锹来挖地基(例子土了点,不过说明问题仍是有效的),后勤部门用铁锹也就是铲铲雪,铲铲垃圾,给工人师傅修修临时住房,因此用量不大,显然两个部门的铁锹自己没有区别,可是这样的划分就为管理两个部门的铁锹提供了方便
线程池中两种线程分别在什么状况下被使用,两者工做原理有什么不一样?
下面这个例子直接说明了两者的区别,咱们用一个流读出一个很大的文件(大一点操做的时间长,便于观察),而后用另外一个输出流把所读出的文件的一部分写到磁盘上
咱们用两种方法建立输出流,分别是
建立了一个异步的流(注意构造函数最后那个true)
FileStream outputfs=new FileStream(writepath, FileMode.Create, FileAccess.Write, FileShare.None,256,true);
建立了一个同步的流
FileStream outputfs = File.OpenWrite(writepath);
 而后在写文件期间查看线程池的情况

string readpath = "e:\RHEL4-U4-i386-AS-disc1.iso";
string writepath = "e:\kakakak.iso";
byte[] buffer = new byte[90000000];

//FileStream outputfs=new FileStream(writepath, FileMode.Create, FileAccess.Write, FileShare.None,256,true);
//Console.WriteLine("异步流");
//建立了一个同步的流

FileStream outputfs = File.OpenWrite(writepath);
Console.WriteLine("同步流");

//而后在写文件期间查看线程池的情况

ShowThreadDetail("初始状态");

FileStream fs = File.OpenRead(readpath);

fs.BeginRead(buffer, 0, 90000000, delegate(IAsyncResult o)
{

outputfs.BeginWrite(buffer, 0, buffer.Length,

delegate(IAsyncResult o1)
    {

Thread.Sleep(1000);

ShowThreadDetail("BeginWrite的回调线程");

}, null);

Thread.Sleep(500);//this is important cause without this, this Thread and the one used for BeginRead May seem to be same one
},

null);

Console.ReadLine();

public static void ShowThreadDetail(string caller)
{
    int IO;
    int Worker;
    ThreadPool.GetAvailableThreads(out Worker, out IO);
    Console.WriteLine("Worker: {0}; IO: {1}", Worker, IO);
}
输出结果

异步流

Worker: 500; IO: 1000

Worker: 500; IO: 999

同步流

Worker: 500; IO: 1000

Worker: 499; IO: 1000

这两个构造函数建立的流均可以使用BeginWrite来异步写数据,可是两者行为不一样,当使用同步的流进行异步写时,经过回调的输出咱们能够看到,他使用的是工做线程,而非IO线程,而异步流使用了IO线程而非工做线程
其实当没有制定异步属性的时候,.Net实现异步IO是用一个子线程调用fs的同步Write方法来实现的,这时这个子线程会一直阻塞直到调用完成.这个子线程其实就是线程池的一个工做线程,因此咱们能够看到,同步流的异步写回调中输出的工做线程数少了一,而使用异步流,在进行异步写时,采用了 IOCP方法,简单说来,就是当BeginWrite执行时,把信息传给硬件驱动程序,而后当即往下执行(注意这里没有额外的线程),而当硬件准备就绪, 就会通知线程池,使用一个IO线程来读取
.Net线程池有什么不足
没有提供方法控制加入线程池的线程:一旦加入线程池,咱们没有办法挂起,终止这些线程,惟一能够作的就是等他本身执行
1)不能为线程设置优先级
2)一个Process中只能有一个实例,它在各个AppDomain是共享的。ThreadPool只提供了静态方法,不只咱们本身添加进去的WorkItem使用这个Pool,并且.net framework中那些BeginXXX、EndXXX之类的方法都会使用此Pool。
3)所支持的Callback不能有返回值。WaitCallback只能带一个object类型的参数,没有任何返回值。
4)不适合用在长期执行某任务的场合。咱们经常须要作一个Service来提供不间断的服务(除非服务器down掉),可是使用ThreadPool并不合适。

下面是另一个网友总结的什么不须要使用线程池,我以为挺好,引用下来
若是您须要使一个任务具备特定的优先级。
若是您具备可能会长时间运行(并所以阻塞其余任务)的任务。
若是您须要将线程放置到单线程单元中(全部 ThreadPool 线程均处于多线程单元中)。
若是您须要与该线程关联的稳定标识。例如,您应使用一个专用线程来停止该线程、将其挂起或按名称发现它。

锁定与同步
CLR怎样实现lock(obj)锁定?
从原理上讲,lock和Syncronized Attribute都是用Moniter.Enter实现的,好比以下代码
object lockobj=new object();
lock(obj){  
//do things 
}
 
在编译时,会被编译为相似
try{
  Moniter.Enter(obj){
   //do things
  }
}
catch{}
finally{
  Moniter.Exit(obj);
}

而[MethodImpl(MethodImplOptions.Synchronized)]标记为同步的方法会在编译时被lock(this)语句所环绕
因此咱们只简单探讨Moniter.Enter的实现
(注:DotNet并不是使用Win32API的CriticalSection来实现Moniter.Enter,不过他为托管对象提供了一个相似的结构叫作Syncblk)
每一个对象实例头部都有一个指针,这个指针指向的结构,包含了对象的锁定信息,当第一次使用Moniter.Enter(obj)时,这个obj对象的锁定结构就会被初时化,第二次调用Moniter.Enter时,会检验这个object的锁定结构,若是锁没有被释放,则调用会阻塞

WaitHandle是什么,他和他的派生类怎么使用
  WaitHandle是Mutex,Semaphore,EventWaitHandler,AutoResetEvent,ManualResetEvent共同的祖先,他们包装了用于同步的内核对象,也就是说是这些内核对象的托管版本。
  Mutex:相似于一个接力棒,拿到接力棒的线程才能够开始跑,固然接力棒一次只属于一个线程(Thread Affinity),若是这个线程不释放接力棒(Mutex.ReleaseMutex),那么没办法,其余全部须要接力棒运行的线程都知道能等着看热闹
Semaphore:相似于一个小桶,里面装了几个小球,凡是拿到小球就能够跑,好比指定小桶里最初有四个小球,那么开始的四个线程就能够直接拿着本身的小球开跑,可是第五个线程一看,小球被拿光了,就只好乖乖的等着有谁放一个小球到小桶里(Semophore.Release),他才能跑,可是这里的游戏规则比较特殊,咱们能够随意向小桶里放入小球,也就是说我能够拿走一个小球,放回去俩,甚至一个都不拿,放回去5个,这样就有五个线程能够拿着这些小球运行了.咱们能够规定小桶里有开始有几个小球(构造函数的第一个参数),也能够规定最多不能超过多少小球(构造函数的第二个参数)
  ManualResetEvent,AutoResetEvent能够参考http://www.cnblogs.com/uubox/archive/2007/12/18/1003953.html
什么是用双锁实现Singleton,为何要这样作,双锁检验是不安全的吗?
使用双锁检验技巧来实现单件,来自于Java社区
public static MySingleton Instance{
get{
    if(_instance!=null)}{
        lock(_instance){
            if(s_valuenull){
                _instance= new MySingleton();
            }
        }
    }
}
}
 
这样作实际上是为了提升效率,比起
public static MySingleton Instance{
get{
lock(_instance){
if(s_value
null){
_instance= new MySingleton();
}
}
前一种方法在instance建立的时候不须要用lock同步,从而增进了效率
在java中这种技巧被证实是不安全的详细见http://www.cs.umd.edu/~pugh/java/memoryModel/
可是在.Net下,这样的技巧是成立的,由于.Net使用了改进的内存模型
而且在.Net下,咱们能够使用LazyInit来实现单件
private static readonly _instance=new MySingleton()
public static MySingleton Instance{
get{return _instance}
}
当第一此使用_instance时,CLR会生成这个对象,之后再访问这个字段,将会直接返回
互斥对象(Mutex),信号量(Semaphore),事件(Event)对象与lock语句的比较
首先这里所谓的事件对象不是System.Event,而是一种用于同步的内核机制
互斥对象和事件对象属于内核对象,利用内核对象进行线程同步,线程必需要在用户模式和内核模式间切换,因此通常效率很低,但利用互斥对象和事件对象这样的内核对象,能够在多个进程中的各个线程间进行同步。
lock或者Moniter是.net用一个特殊结构实现的,不涉及模式切换,也就是说工做在用户方式下,同步速度较快,可是不能跨进程同步

何时须要锁定?
刚刚接触锁定的程序员每每以为这个世界很是的危险,每一个静态变量彷佛都有可能产生竞争
首先锁定是解决竞争条件的,也就是多个线程同时访问某个资源,形成意想不到的结果,好比,最简单的状况,一个计数器,若是两个线程同时加一,后果就是损失了一个计数,可是频繁的锁定又可能带来性能上的消耗,还有最可怕的状况,死锁
到底什么状况下咱们须要使用锁,什么状况下不用呢?
只有共享资源才须要锁定
首先,只有能够被多线程访问的共享资源才须要考虑锁定,好比静态变量,再好比某些缓存中的值,属于线程内部的变量不须要锁定
把锁定交给数据库
数据库除了存储数据以外,还有一个重要的用途就是同步,数据库自己用了一套复杂的机制来保证数据的可靠和一致性,这就为咱们节省了不少的精力.保证了数据源头上的同步,咱们多数的精力就能够集中在缓存等其余一些资源的同步访问上了
了解你的程序是怎么运行的
实际上在web开发中大多数逻辑都是在单个线程中展开的,不管asp.net仍是php,一个请求都会在一个单独的线程中处理,其中的大部分变量都是属于这个线程的,根本没有必要考虑锁定,固然对于asp.net中的application对象中的数据,咱们就要当心一些了
WinForm中凡是使用BeginInvoke和Invoke调用的方法也都不须要考虑同步,由于这用这两个方法调用的方法会在UI线程中执行,所以实际是同步的,因此若是调用的方法中存在某些静态变量,不须要考虑锁定
业务逻辑对事务和线程安全的要求
这条是最根本的东西,开发彻底线程安全的程序是件很费时费力的事情,在电子商务等涉及金融系统的案例中,许多逻辑都必须严格的线程安全,因此咱们不得不牺牲一些性能,和不少的开发时间来作这方面的工做,而通常的应用中,许多状况下虽然程序有竞争的危险,咱们仍是能够不使用锁定,好比有的时候计数器少一多一,对结果无伤大雅的状况下,咱们就能够不用去管他
计算一下冲突的可能性
我之前曾经谈到过,架构不要过设计,其实在这里也同样,假如你的全局缓存里的某个值天天只有几百或者几千个访问,而且访问时间很短,而且分布均匀(实际上这是大多数的状况),那么冲突的可能性就很是的少,也许每500天才会出现一次或者更长,从7*24小时安全服务的角度来看,也彻底符合要求,那么你还会为这样万分之一的可能性花80%的精力去设计吗?
请多使用lock,少用Mutex
若是你必定要使用锁定,请尽可能不要使用内核模块的锁定机制,好比.net的Mutex,Semaphore,AutoResetEvent,ManuResetEvent,使用这样的机制涉及到了系统在用户模式和内核模式间的切换,因此性能差不少,可是他们的优势是能够跨进程同步线程,因此应该清楚的了解到他们的不一样和适用范围

Web和IIS
应用程序池,WebApplication,和线程池之间有什么关系
一个应用程序池是一个独立的进程,拥有一个线程池,应用程序池中能够有多个WebApplication,每一个运行在一个单独的AppDomain中,这些WebApplication公用一个线程池
不一样的AppDomain保证了每一个WebApplication的静态变量不会互相干扰,不一样的应用程序池保证了一个网站瘫痪,其余不一样进程中的站点还能正常运行
 下图说明了他们的关系

Web页面怎么调用异步WebService
把Page的Async属性设置为true,就能够调用异步的方法,可是这样调用的效果可能并不如咱们的相像,请参考Web中使用多线程来加强用户体验

序列化和反序列化的实现
http://www.javashuo.com/article/p-zvdeasuu-h.html

C#模态对话框和非模态对话框
模态对话框
弹出窗口阻止调用窗口的全部消息响应。
只有在弹出窗口结束后调用窗口才能继续。
在模态窗口“关闭”后,能够读取模态窗口中信息,包括窗口的返回状态,窗口子控件的值。

非模态对话框
能够在弹出窗口和调用窗口之间随意切换。
调用窗口调用show方法后,下面的代码能够当即执行。在非模态窗口关闭后,窗口的全部资源被释放,窗口不存在,没法获取窗口的任何信息。
所谓模态对话框,就是指除非采起有效的关闭手段,用户的鼠标焦点或者输入光标将一直停留在其上的对话框。非模态对话框则不会强制此种特性,用户能够在当前对话框以及其余窗口间进行切换 
概念说明
1 模态窗口
打开模态窗口后,只要不关闭该窗口,鼠标焦点或者光标就会一直停留在该窗口上。只有关闭该窗口后,调用窗口才能继续。模态窗口关闭后,仍能够读取模态窗口中的信息,如窗口的返回状态等。
2 非模态窗口
打开非模态窗口后,仍能够操做调用窗口。关闭非模态窗口,该窗口将不复存在,会释放窗口的全部资源,因此没法获得该窗口的任何信息。
 
实例说明
1 创建Windows窗体程序ShowAndShowDialogExp,程序主画面包含两个按钮,用于打开模态窗口和非模态窗口(以下图所示)。
 
2 编写按钮的Click事件代码

private void button1_Click(object sender, EventArgs e)
{
Form frm1 = new Form();
frm1.Text = "我是模态窗口!";
frm1.ShowDialog();//打开模态窗口(对话框)}
private void button2_Click(object sender, EventArgs e)
{
Form frm2 = new Form();
frm2.Text = "我是非模态窗口!";
frm2.Show();//打开非模态窗口(对话框)
}

3 运行代码,进行操做体验
点击按钮“打开模态窗口”,打开模态窗口frm1,窗口标题栏显示“我是模态窗口!”,此时没法切换到调用窗口,当关闭该窗口后,又能够继续操做调用窗口了。
点击按钮“打开非模态窗口”,打开非模态窗口frm2,此时,能够仍切换到调用窗口操做调用窗口。
 
4 实例结论
C#中使用Show()方法打开非模态窗口,使用ShowDialog()方法打开模态窗口。
 
5 进阶
修改前面按钮的Click事件代码,修改后的代码以下所示。

private void button1_Click(object sender, EventArgs e)
{
Form frm1 = new Form();
frm1.Text = "我是模态窗口!";
frm1.ShowDialog();//打开模态窗口(辍对话框)MessageBox.Show(frm1.DialogResult.ToString());
}
private void button2_Click(object sender, EventArgs e)
{
Form frm2 = new Form();
frm2.Text = "我是非模态窗口!";
frm2.Show();//打开非模态窗口(对话框)MessageBox.Show(frm2.DialogResult.ToString());
}

朋友,发现跟前面代码的区别了吗?
呵呵,仅仅加了一句输出弹出窗口的DialogResult属性值的代码而已。
再次执行代码,程序的运行状况是:
点击“打开模态窗口”打开模态窗口,接着关闭模态窗口,会弹出消息框,输出“Cancel”(frm1.DialogResult.ToString()的结果)。
点击“打开非模态窗口”打开非模态窗口后,便会弹出消息框,输出“None”(frm2.DialogResult.ToString()的结果)。
从程序执行状况咱们了解到:
执行Show()方法后,后面的代码会当即执行;而执行ShowDialog()方法后,后面的代码须要等弹出窗口关闭后才能及时执行。
 
前面说到:模态窗口关闭后,仍能够读取模态窗口中的信息。
这主要是由于:当“关闭”模态窗口后,窗体并无被真的被“关闭”,由于用户点击“关闭”按钮或者设置DialogResult属性值时,并无调用窗体的Close方法,只是将窗体的Visible属性赋值为false,隐藏了窗体而已。这样隐藏的窗体是能够被从新显示的,且窗体资源并无被释放。因此,在你真的不须要这个窗体时,必定要记得Dispose一下哦。
为了说明这一切,修改前面打开模态窗口的按钮Click事件代码。

private void button1_Click(object sender, EventArgs e)
{
Form frm1 = new Form();
frm1.Text = "我是模态窗口!";
frm1.ShowDialog();//打开模态窗口(对话框)MessageBox.Show(frm1.DialogResult.ToString());
frm1.Visible = true;
}

模块之间的接口应该尽可能少而简单。
Web api:http://www.javashuo.com/article/p-ygftwkxz-kp.html

相关文章
相关标签/搜索