基础知识 -- 问答

ASP.NET 同时被 3 个专栏收录
4 篇文章 0 订阅
3 篇文章 0 订阅
1 篇文章 0 订阅
01.Main函数是什么?在程序中使用Main函数有什么需要注意的地方?
Q:程序的入口函数!函数名字不能改变;一个程序中有且只有一个Main函数。

02.CLR是什么?程序集是什么?当运行一个程序集的时候,CLR做了什么事情?
Q:Common Language RunTime 公共语言运行时。 
编译后代码的集合。(包括exe和dll)。 加载项目里所有的类到内存,并找到其中的主函数,并作为默认的启动函数调用执行。

03.值类型的默认值是什么?(情况一:字段或全局静态变量;情况二:局部变量)
Q:如果是全局变量,并且没赋值,就会有默认值,如:int 是0;bool 是false;枚举enum;结构体struct;
  如果是局部变量,就必须手动赋值。

04.声明一个变量时在内存中做了什么事情?初始化一个变量的时候又在内存中做了什么事情?
Q:在栈中开辟空间,并将变量放入空间里,默认值都是null。
 初始化时:
如果是值类型,则直接放入栈中;
如果是引用类型,则在堆中开辟一块空间,将堆中对象的地址指针放入栈中,


05.new关键字做的事情?
Q:开辟空间,创建对象,调用构造函数。

06.数组
    061.数组一旦创建后,能不能修改数组的长度?
Q:不能。为什么呢?数组是引用类型。它在创建时,已经根据创建的长度在内存中开辟一块连续的空间。

07.多维数组
    071.如何声明一个多维数组?
Q:多维数组string[,] strArr=new string[3,3];  

    072.如何获取多维数组的总长度?
Q:各个纬度元素的个数的乘积 

08.交错数组
    081.如何声明一个交错数组?
Q:交错数组:int[][] arr=new int[3][3];

    082.交错数组的本质是什么?
Q:本质是一个数组的数组。简单的说这个数组的元素是一个数组。




2012 - 0213
-------------
01.为什么要有方法?
Q:为了复用。(封装)(重复调用,封装具体实现)

02.如何实现方法的重载?
Q:方法名相同,但签名不同。(和返回值无关)

03.引用参数(ref)和输出参数(out)的相同点与不同点?
Q:相同点:传递的都是引用。
  不同点:
out侧重于输出参数;ref侧重于修改;
out必须方法返回之前赋值;ref必须在传入之前赋值。


04.在什么情况下使用引用参数(ref)和输出参数(out)?
Q:如果方法有多个返回值,则可以用out或者ref。只不过ref侧重于修改(即将值传进去修改后再拿出来);而out是为了从方法中获得一个值后拿到方法外使用。
05.可变参数与普通数组参数的区别?
Q:params关键字。
特点:
一个方法中只能有一个可变参数;
而且必须放在参数列表最后;
如果没有给可变参数赋值,就初始化长度为0;


2012 - 0215
-------------
01.面向对象的三大特征是什么?
Q:封装;继承;多态;

02.类和对象的关系?
Q:抽象和具体的关系。类是抽象(模板,设计图纸),对象是具体(按照图纸设计的房子)。类是对对象的抽象描述,而对象是类的具体化。

03.创建某一个类的对象的时候,在内存中做了什么事情?例如 Person p = new Person();
Q:开辟空间,创建对象,调用构造函数。(在内存的堆中开辟空间,创建Person对象,然后在内存的栈中开辟一个放一个p,然后将Person对象在堆中的引用地址赋值给对象p)
04.属性存在的目的是什么?
Q:封装字段。为了对字段的操作设置规则。(本质是两个方法,一个get方法和一个set方法)
05.访问修饰符有哪些并分别每一个访问修饰符?
Q:public(公有的),
  private(只有本类可以访问),
  internal(程序集内共享,如果不写修饰符,默认就是internal),
  protected(本类和子类可以访问),
  extern(供外部访问,eg:C#提供接口给C++访问)
06.为什么要有构造函数呢?
Q:主要方便程序猿在实例化对象的时候就为对象里的一些属性和字段初始化赋值。
07.什么是封装?封装的目的是什么?
Q:封装就是将对象的字段、行为和功能等“弄”到一起。
  封装的目的:隐蔽代码实现/复用/修改方便
08.类的命名规则是什么?
Q:类命名:首字母大写(帕斯卡命名)。变量命名:首字母小写(骆驼命名)




2012 - 0216
-------------
01.什么是类型?
Q:用来定义某一种数据在内存里开辟空间的大小,还可以预置操作此种类型数据的相关方法

02.this关键字在方法中使用时,它代表什么?
Q:this指当前类的对象,或者他的父类的类对象。
 base只能指向父类的对象。

03.值类型变量的初始化(内存分配)?(两种情况:一是类的成员变量,二是:方法的局部变量)
Q:1、当变量是一个类的成员变量的时候,那么该变量是跟随累的对象存在于堆内存。当对象引用断开时,等着垃圾回收器进行清理时便被销毁
  2、当变量是一个方法的局域变量时,那么该变量是在方法被调用时,存在于栈内存,方法执行完毕后被销毁


04.继承
    041.继承的好处?
Q:1.提高代码的复用;
 2.实现多态;
 
    042.继承的单根性
Q:一个类只能继承一个父类。

043.继承的传递性
Q:指子类只能继承父类的非私有的成员。

    044.当存在继承关系的时候,在子类中如何访问父类的非私有成员?
Q:通过base关键字--(只能获取父类的)(base就是存在于子类对象里,用来指向父类对象的指针)
  或者通过this关键字--(可以获取父类的非私有的成员和本类的成员)

05.什么是里氏替换原则?
Q:子类替换父类所在的位置

06.子类与父类对象之间的转换?
Q:子类可以强制转换为父类,但是父类不能转换为子类。

07.is 和 as 操作符的用处和区别?
Q:is是对类型的判断,返回bool。(判断A是否是B类,或者A是不是B的子类)。(如果一个对象是某个类型或是其父类型的话就返回true,否则就会返回为false。另外is操作符永远不会抛出异常。
  as是用来做类型转换的。as只能针对引用类型的转换。as 是先判断再转换(as 操作符首先测试转换是否合法,如果合法就转换,否则返回NULL。不会报错)
  这两者都不会抛出异常。
  
  08.override可以重写哪些 "类型" 的方法?
Q:可以重写虚方法(virtual)--必须有方法体
  还可以重写抽象方法 (abstract)--没有方法体
  
09.什么是多态?
Q:就是用某个子类来实例化父类,调用的是父类的抽象方法(虚方法),但实际执行的是子类实例重写的方法


10.抽象方法只能定义在抽象类中吗?
Q:是的。
(virtual or abstract members cannot be private)



2012 - 0217
-------------
01.CLR什么时候加载类?
Q:是在第一次在代码中遇到这个类的时候才加载类的静态成员和信息。(为了节约资源,只在用的时候才开始加载进去)

02.当存在继承关系的时候,创建子类对象的时候会不会创建父类对象呢?
Q:这个很易错!!!!当 我们 创建一个子类时不会创建父类对象,只会有一个对象。Person c=new Student(),(当 我们 new一个子类的时候,在内存中,只有一个子类对象)
!!--!!----那下面括号里面的就是错误的!!!
(new子类时,先创建子类对象,调用子类的构造函数时,创建父类对象,调用父类构造函数最后返回来执行子类构造函数方法体代码

子类默认调用父类的无参构造函数
如果父类里没有无参构造函数,则必须显示的调用)

03.如果子类和父类存在同名但没有重写关系的方法的时候,那么会调用哪个方法?(两种情况:一是使用子类对象,而是使用父类对象)
Q:如果子类和父类存在同名但没有重写关系的方法,那么调用时,如果是父类变量调用,则调用父类方法,如果是子类变量调用,则调用子类方法


04.如果子类和父类存在同名且有重写关系的方法,那么会调用那个方法?(两种情况:一是使用子类对象,而是使用父类对象)
Q:如果子类和父类存在同名且有重写关系的方法,那么不管变量是什么类型,调用的都是子类的方法。


05.虚方法和抽象方法的相同点与不同点?
Q :相同点:都能被子类重写;都不能为私有的
  不同点:
1.abstract 和virtual的关键字不同
2.抽象方法一定没有方法体,而虚方法必须有方法体。
   3.virtual方法的子类可以重写父类方法也可不重写,而抽象方法的所在的类的子类必须重写该父类方法
4.抽象方法必须在抽象类中声明,而虚方法可以存在于任何一个类里面
5.virtual方法必须有现实(哪怕是空实现),而abstract方法必须没有实现


06.子类中的base关键字指向的是子类对象还是父类对象?它本身的类型是子类类型还是父类类型呢?
Q:当然是指向的父类对象。 但是本身是子类的类型。
(base就是子类对象本身,只不过类型是父类)

07.为什么要有抽象类?
Q:抽象类存在的目的就是指定规则,而不是具体实现,是为了约束子类的行为,具体实现交给子类完成。

08.使用多态的好处是什么?
Q:1.低耦合,高内聚。(低耦合---代码的内部各个层之间的关联小,相互之间约束少。 高内聚---方法的功能和职责单一,即一个方法只做一件事情。)
  2.实现代码的可维护性 和 可扩展性。
  3.把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。
  
09.什么情况下的类不能被实例化?
Q:1.抽象类
  2.静态类
  3.类的构造函数被私有化
  
10.什么情况下抽象类的子类不需要实现父类的抽象成员?
Q:子类也是抽象类的时候。

11.虚方法(虚拟成员)和抽象方法(抽象成员)能不能被私有化?
Q:当然不能。(首先编译就会报错)。---深层原因:他们两者存在的目的就是为了让子类去重写,如果私有化了,就没意义了。

12.静态成员能不能被标记为virtual、override 或 abstract?
Q:不能:

13.接口的命名规则?
Q:以大写I为开头,以...able结尾。表示有某种能力。

14.什么是接口?
Q:特殊的抽象类。他的存在完全是为了约束和统一类的行为。

15.接口能包含的成员有哪些?
Q:接口只有方法、属性、索引器和事件的声明

16.接口的访问权限修饰符只能是哪两种?
Q:public和internal 


17.接口能不能继承接口?
Q:能。而且可以实现多个接口。

18.如果一个抽象类继承了一个接口,那么将继承的方法设置为抽象方法,还是去实现该方法?
Q:都可以。 既可以在抽象类的子类中去实现,也可在抽象类中直接实现。




--------------------------------------------------------------------
付炯 2月19日
1、使用接口的注意事项
Q:1,接口中的成员不能加访问修饰符;
 2,接口中的成员不能有任何实现;
          3,实现接口的子类的必须实现接口的全部 成员;
 4,接口中只能有方法,属性,索引器,事件,不能有字段。
          5,一个类可以同时继承一个类并实现多个接口,如果一个子类同时继承了父类A,并实现了接口IA,那么在语法上A必须写在IA的前面,因为类是单继承的,而接口可以实现多个。
 6,显示实现接口和隐式实现接口时需要注意的问题,(通常 我们 是隐式实现的),
 类实现接口,可以显式的实现接口里的方法,但是注意:一旦使用显式实现接口里的方法后,那么该方法只能被接口变量调用
 IFlyable fly = new Bird();
 fly.Fly();  //正确
 Bird fly = new Bird();
 fly.Fly();  //错误

         7,向上转型
 
         8,单一职责原则 (避免定义体积庞大的接口,因为这样会造成“接口污染”,只把相关联的一组成员定义到一个接口中)
 
2、接口与抽象类的区别
Q:相同点:
接口和抽象类都不能被实例化;
  不同点:
             1,接口中不能存在有具体实现的方法;而抽象类中可以有具体的方法实现。(接口只能定义行为,而抽象类既可以定义行为也可以提供实现)
             2,接口支持多继承,而抽象类不能实现多继承;
     3,接口可以定义方法Method,属性property,索引器Index,事件Event的签名,但不能定义字段和这些东西的具体实现,而抽象类什么都能定义和实现,除了       不能被实例化
 
 老邹的2011年答案:
   1) 抽象基类可以定义字段、属性、方法实现。接口只能定义属性、索引器、事件、和方法
声明,不能包含字段。 
2) 抽象类是一个不完整的类,需要进一步细化,而接口是一个行为规范。微软的自定义接
口总是后带able字段,证明其是表述一类“我能做。。。”。 
3) 接口可以被多重实现,抽象类只能被单一继承。 
4) 抽象类更多的是定义在一系列紧密相关的类间, 而接口大多数是关系疏松但都实现某一
功能的类中。 
5) 抽象类是从一系列相关对象中抽象出来的概念, 因此反映的是事物的内部共性;接口
是为了满足外部调用而定义的一个功能约定, 因此反映的是事物的外部特性。 
6) 接口基本上不具备继承的任何具体特点,它仅仅承诺了能够调用的方法。    
7) 接口可以用于支持回调,而继承并不具备这个特点。 
8) 抽象类实现的具体方法默认为虚的, 但实现接口的类中的接口方法却默认为非虚的, 当
然您也可以声明为虚的。 
9) 如果抽象类实现接口,则可以把接口中方法映射到抽象类中作为抽象方法而不必实现,
而在抽象类的子类中实现接口中方法

3、类型转换
转换分类
Q:隐式转换 int  num = 1; string str= num.tostring();
      强制转换 int a =  5; (double ) b= a;

转换条件

ToString()方法
    Q:它是object对象的一个虚方法,可以自己去重写该方法。如果不重写就返回类型名。


Parse()和TryParse()方法
Q:相同点:都是针对于字符串进行的值类型转换。
  不通点:1,返回值不一样。Parse()是返回要转换的类型,而TryParse()返回一个转换是否成功的bool值。
 2,Parse()转换失败会拋异常,而TryParse()转换失败返回false,不会拋异常。
 3,Parse()直接传入要转换的类型的值,而TryParse()需要一个out输出参数输出转换的结果。

4、静态成员
          加载时机 (什么时候加载静态成员?)
  Q:在该静态成员第一次被调用的时候加载。
 
       适用情形(什么时候用静态成员?)
Q:在整个程序内部共享的数据才定义为静态的。通常被作为工具类使用。比如SQLHelper

    在普通类和静态类中的区别
Q:1,静态类需要用static。静态类不能被实例化。
  2,静态类中只能包含静态成员;
  3,静态成员属于类所有,非静态成员属于类的实例所有。
  4,在实例方法中可以直接调用静态成员,但在静态方法中不能直接调用实例方法。
  5,静态类和静态变量创建后始终使用同一块内存,而使用实例的方法会创建多个内存。
  6,静态构造函数不能有参数,也不能有访问修饰符(默认是private)
  
5、静态类的继承
Q:1,(从子类的角度)静态类不能被任何类继承
2,(从父类的角度)静态类只能继承Object类,不能继承其他的类。




6、类和成员的访问修饰符
Q:1,类的默认访问修饰符是internal,
   2,类的成员的默认访问修饰符是private

a.类的访问修饰符只有两种:public,internal(默认)
b.成员的访问修饰符有:public,protected,private(默认)

7、结构
    本质是值类型
    值类型和引用类型的选择
Q:1.值类型:主要是用来封装一组数据,并为数据提供一种简单的处理方式
 2引用类型:
 1).主要用来封装数据和行为
 2)使用面向对象的特征;
 3)当类型中的成员比较多的时候用结构(存在堆里)
 
    new关键字的作用
Q:结构 
      在使用new关键字创建对象后,所有的成员变量都已经存在,并有默认值(值类型)
  如果没有用new关键字,则需要程序员手动为所有的  用到了  的成员变量赋值,之后才能调用结构对象里的方法属性
  结构不new也可以使用,但是必须给使用到的结构成员赋值才能使用

8、类和结构的区别
Q:1,结构是值类型,是分配在内存的栈上的。而类是引用类型,是分配在内存的堆上的;
  2,结构不能被继承,因为结构是值类型,隐式继承自System.ValueType
  3,结构是值传递的(复制传递),而类是引用传递的。

9、值类型和引用类型作为参数传递的区别
Q:值类型是值传递的(复制传递),而类是引用传递的(传的是地址的引用)。

10、访问级别约束
Q:1,子类的访问级别不能比父类高
  2,方法参数的访问级别  >=  方法的访问级别  (比如当方法的参数传递的是一个类对象时,那么此时这个类对象的访问级别要高于当前方法的访问级别)

11、析构函数
Q:1,一个类只能有一个析构函数,
  2,无法继承或重载析构函数
  3, 我们 无法手动去调用析构函数,因为它是被GC(垃圾回收器)自动调用的
  4,析构函数不能有访问修饰符,也不能有参数
  5,不能在结构体中定义析构函数(为什么呢?)--因为结构是值类型,而值类型是存储在栈中的,栈中的数据在用完之后就立即销毁了,而析构函数的目的就是用来释放资源的,一般存储在堆中的引用类型才需要GC去释放,因而结构体中是不能定义析构函数的,只能对类使用析构函数。
  
  析构函数语法:
  class MyDispose
  {
~MyDispose()
{
......//在这里写释放资源的代码
}
  }

12、字符串
    属性
length
    静态方法
常用:
1、(Last)IndexOf:用来查找某个字符或字符串,在一个特定字符串对象里的下标
2、SubString 截取
3、Split() 根据特定字符来分割字符串,并返回分割后的字符串的数组,可以用foreach读取
4、Join静态方法
5、Format() 静态方法
6、Replace(),替换完要接收,产生一个新的字符串
7,Replace().Replace()链式编程
8、Trim()去首尾空格

    实例方法

13、==运算符和Equals()方法的区别
Q:"=="比较时:
如果比较的是值类型,则比较两个对象的值
如果比较的是引用类型,则比较两个对象的引用地址是否相同(比较堆地址)
“Equals”比较时:
此方法是Object类里的一个虚方法,默认就是用的“==”进行比较。(它是对“==”进行的一个封装)
但是,大部分微软的类,及用户自定义的类,都重写了该虚方法,也就是微软和用户各自为自己编写的Object的子类 定义了相等比较规则。
注意:这里有一个特例,因为string是一个引用类型,所以按理说string.Equals(...)方法比较的是地址,而这里比较的字符串的值。

14、字符串的恒定性
Q:当字符串在内存中已经被创建后,程序员在次创建相同值的字符串对象时,CLR做了优化,直接把第一个字符串的引用赋给了第二个变量,也就是说,前后两个字符串变量保存了相同的字符串对象应用

15、StringBuilder对象
Q:高效的的字符串操作。
String 在进行运算时(如赋值、拼接等)会产生一个新的实例,而 StringBuilder 则不
会 。 所以在大量字符串拼接或频繁对某一字符串进行操作时最好使用 StringBuilder , 不要使
用 String
如果要操作一个不断增长的字符串,尽量不用 String 类 , 改用 StringBuilder 类。两个类的工
作原理不同 :String 类是一种传统的修改字符串的方式 , 它确实可以完成把一个字符串添加到
另一个字符串上的工作没错 , 但是在 .NET 框架下 , 这个操作实在是划不来 。 因为系统先是把
两个字符串写入内存 , 接着删除原来的 String 对象 , 然后创建一个 String 对象 , 并读取内存
中的数据赋给该对象。这一来二去的,耗了不少时间。而使用 System.Text 命名空间下面 的
StringBuilder 类就不是这样了,它提供的 Append 方法,能够在已有对象的原地进行字符串
的修改 , 简单而且直接 。 当然 , 一般情况下觉察不到这二者效率的差异 , 但如果你要对某个
字符串进行大量的添加操作 , 那么 StringBuilder 类所耗费的时间和 String 类简直不是一个数
量级的。

16、枚举
    本质是类
    枚举项的相关问题
Q:1、如果为第一个枚举项赋了一个int值,那么后面的枚举项依次递增。
2、可以将枚举强转成他所代表的int值
3、因为枚举项都有对应的int值,所以Switch把他当成int看
4、C#的枚举项都是常量(可以去看IL 代码 literal)
5、不能定义方法,属性,事件
6、多个枚举有相同数值时。数值强转时,会返回其中最后一个枚举项
7、枚举项的数值类型int ,long....

17、IEnumerable接口
Q:只要实现了该接口,就可以使用foreach进行遍历。 foreach循环的本质就是调用这个接口返回一个迭代器,调用迭代器的MoveNext()方法就可以实现循环。
   如下反编译的源码:
   public interface IEnumerable
{
IEnumerator GetEnumerator();   //返回一个迭代器
}

public interface IEnumerator
{
bool MoveNext();
object Current { get; }
void Reset();
}

    从以上反编译源码可以看出:  
IEnumerable接口中主要包含GetEnumerable方法(获取迭代器对象),MoveNext方法(检查是否存在循环的下一个元素),GetCurrent方法(获得当前循环到的元素)


2月20日
1、集合
    概念理解
Q: 集合就是能装一堆东西的容器。主要分为非泛型集合和泛型集合。
Arraylist--- 里面真正存储数据的是一个Object[]数组,它对应的泛型是List<T>,
HashTable---非泛型的键值对集合,它对应的泛型是Dictionary<TKey,TValue>


动态数组和泛型集合的不同点和优缺点:
Q:不同点:  
动态数组对元素没有任何约束,想添加什么都可以。其根本原因是:因为其内部存储数据的是一个Object类型的数组。
泛型集合是带元素类型约束的集合(对添加里面的元素有一个约束)
我们 要尽可能的使用泛型集合:(其优点有)
1,避免了装箱,拆箱操作带来的性能损耗;
2,在添加元素时岁参数类型进行检查(编译时就检查)


    常用方法
Q:泛型的list有常用方法:add(), AddRange(),iInsert(),InsertRange(),remove(),removeAt()
  Reverse()---- 将集合中的元素反转,很实用

2、哈希表
内部机制
Q:HashTable,键值对集合,其内部是一个结构体数组bucket[]。有三个东西(键,值,键的哈西码)
这是里面存储数据的东西:private bucket[] buckets;
private struct bucket
{
public object key;
public object val;
public int hash_coll;
}


    存取操作
   Q:
A:如何存????原理:
1.下标是根据key的hash值算出来的。当 我们 向Hashtable中Add元素时,元素储存在HashTable的数组里的下标是根据添加key的hash值算出来的(但因为hash值取模数组长度,所以肯定不会超过当前数组长度)
2、每个对象算出来的Hashcode并不是唯一的。有可能出现多个对象的Hashcode相同。
解决机制:
1)再次hash一次。
2)桶装模式,将两个相同hashcode的对象装入同一个位置
3.当新增时,HashTable里的容器数组已经满了,则以数组的两倍扩容。


B:如何取????原理:
我们 从HashTable里取元素时(根据key来取),会根据key的hash值算出要取的元素的下标,并比较元素里的key和当前要找的key参数的hash值是否相等,同时还要比较两个key的引用是否一致。如果都满足,则确定找到要取的元素。


3、泛型集合
Q:引用命名空间:System.Collections.Generic
   List<T>----T是存储的类型
   Dictionary<K, V>

4、List<T>和ArrayList的性能比较
Q :ArrayList存值类型需要装箱猜想,而存储引用类型需要类型转换,而List<T>很明显不需要这些额外的开销。那个性能高显而易见。

5、应该使用try语句块的情况
Q:网络操作(套接字),文件操作(IO相关),数据库操作,除法操作(除数为0的时候),强制类型转换操作

2月22日
1、Windows Form程序相关文件
Q:designer.cs设计类和前台两个类是 兄弟类的关系(partial)

2、Path类
Q: ChangeExtension(修改文件的后缀,“修改”支持字符串层面的,没有真的给文件改名)
Combine(将两个路径合成一个路径【自动处理路径分隔符的问题】)
GetDirectoryName(得到文件的路径名)
GetExtension(得到文件的扩展名)
GetFileName(得到文件路径的文件名部分)
GetFileNameWithoutExtension(得到去除扩展名的文件名)
GetFullPath(得到文件的全路径,可以根据相对路径获得绝对路径)
GetTempFileName(得到一个唯一的临时文件名)
GetTempPath(得到临时文件夹的路径)
.........

3、操作目录、文件夹(Directory)
Q: Delete(删除目录【recursive表示是否递归删除】)
Exists(判断目录是否存在)
move(移动)
GetDirectories(得到一个目录下的子目录)
GetFiles(得到一个目录下的文件)
........

4、操作文件
Q:File(操作文件,静态类,对文件整体操作。拷贝、删除、剪切等。)
AppendAllText(将文本contents附加到文件path中【如果文件不存在,则创建】)
Exists(判断文件path是否存在)
ReadAllLines(读取文本文件到字符串数组中)
ReadAllText(读取文本文件到字符串中)
WriteAllText(将文本contents保存到文件path中,会覆盖旧内容)
WriteAllLines(将字符串数组逐行保存到文件path中,会覆盖旧内容)
Copy(文件拷贝【true表示当文件存在时“覆盖”,如果不加true,则文件存在报异常】)
Create(创建文件)
Delete(如果文件不存在?不存在,不报错)
.........
结合下面的
DirectoryInfo(文件夹的一个“类”,用来描述一个文件夹对象)
GetParent(得到目录的父目录)
   FileInfo(文件类,用来描述一个文件对象)
..........

注意:
1,获取当前exe文件执行的路径用(Assemby.GetExecutingAssembly().Location)不要用Directory.GetCurrentDirectory(),因为获取的是程序当前工作目录,这个路径可能会变
2,修改文本编码通过GetEncoding获得该编码。

5、文件流
Q :FileStream(任意类型)
StreamWriter (字符串写)
StreamReader(字符串读)
6、using语句的本质
Q:1,本质是一个try{...}finally{...}语句块;
   2,所有要使用Using关键字来释放资源的类都必须实现IDisposable接口;
3,Close执行了Dispose()并回收对象;
注意:使用Using语句块并不能抓住异常,因为Using里面只做了try finally操作,而没有catch语句块,所以在Using语句块中还是要自己加上try catch块来捕捉异常。


7、序列化和反序列化
Serializable特性
二进制格式化器
Q:
A:序列化-----(二进制格式化器,将对象里的字段及值以“文本”的方式保存成文件) [Serializable]
BinaryFormatter类方法
1.Serialize(对象graph序列化到stream中)
2.Deserialize(将对象从stream中反序列化,返回值为反序列化得到的对象)
二进制序列化注意事项
1.要序列化的类型必须标记为:[Serializable]
2.该类型的父类也必须标记为:[Serializable](反射的时候有一个参数必须是:是否寻找父类对象)
3.该类型中的所有成员的类型也必须标记为:[Serializable]
4.序列化只会对类中的字段序列号(只能序列化一些状态信息。)
B:反序列化-----(二进制格式化器,先创建一个相同的对象,然后将“文本”里保存的字段的值设置到字段中。按照文本(字段、字段值、类名)信息里的类名,使用反射 技术创建新对象,并将对一个的字段值设置到新的对象中)

2月23日
1、委托
    概念理解
Q : 通俗的说,委托就是一个存放方法指针的容器,是一个安全的函数指针。供程序员安全调用。
     委托的本质就是一个类,继承于MulticastDelegate->Delegate,在Delegate类中有一个IntPtr类型的变量用来指向该方法的指针。
 
    适用情形
Q:当方法传递的参数为一个方法时,就用委托。

    委托作用
Q:1.能够将方法作为参数传递
      2.(多播委托)调用一个委托,执行N个方法。


    Delegate类
2、集合排序
Q:1,Reverse()方法直接反转排序
 2,冒泡排序
for(int i = 0; i<arr.length;i ++)
{
for(int j = 0; j <arr.length-i-1;j++)
{
if(arr[j] > arr[j+1])
{
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}

3、匿名方法
Q:  1,并不是真的没有名字,它在CLR编译时会产生一个临时方法名。
       2,匿名方法产生后,方法指针会存放在委托变量中,共程序调用

4、多播委托
Q: 1,可以向委托上注册多个方法 (+=)
    2,也可以从委托上移除已注册的方法 (-=)
    3,如果委托上注册了多个有返回值的方法,那么调用之后委托返回的是最后一个方法的返回值


2月24日
1、事件
    事件本质
Q:本质就是提供了一个Add和Remove方法的委托对象。
(IL编译后生成了一个私有的委托对象,同时又为该委托对象提供了一个add(+=)和一个remove(-=)方法)

    内部机制
Q:创建一个私有的委托对象,同时又为该委托对象提供了一个add(+=)和一个remove(-=)方法,让程序员只有+=和-=的操作。

2、委托和事件的区别
Q:委托和事件没有可比性,因为委托是类型,事件是对象,下面说的是委托的对象(用委托方
式实现的事件)和(标准的 event 方式实现)事件的区别。事件的内部是用委托实现的。因
为对于事件来讲,外部只能“注册自己+=、注销自己-=” ,外界不可以注销其他的注册者,
外界不可以主动触发事件, 因此如果用 Delegate 就没法进行上面的控制, 因此诞生了事件这
种语法。 事件是用来阉割委托实例的, 类比用一个自定义类阉割 List。 事件只能 add、 remove
自己,不能赋值。事件只能+=、-=,不能= 。


-----------------------------------------------------------------
课程日期:2-24,2-26,2-27,2-29,3-1


1. 2-24知识点:(课程签名:事件)
  1.1事件的定义
Q : public event 

  1.2事件和委托的关系
Q:见上.

  1.3事件出现的意义
  
  1.4事件的简单使用
Q:
delegate void MyDelegate(string name);
class Program
{
static event MyDelegate myEvent;
static void Main(string[] args)
{
myEvent += new MyDelegate(Program_myEvent);
Console.ReadKey();
}
static void Program_myEvent(string name)
{
throw new NotImplementedException();
}
}

2. 2-26知识点:(课程签名:SQL初级)
  2.1数据库的概念
Q:SQL(Structured Query                  Language)结构化查询语言,是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统。同时也是数据库脚本文件的扩展名。
SQL语言包含3个部分:
  数据定义语言Data Definition Language(DDL),定义:definition/ 例如:CREATE、DROP、ALTER等语句。
  数据操作语言Data Manipulation Language(DML),操作:make/ 例如:SELECT(查询),INSERT(插入)、UPDATE(修改)、DELETE(删除)语句。
  数据控制语言Data Controlling Language(DCL),控制:control/ 例如:GRANT、REVOKE、COMMIT、ROLLBACK等语句。
  SQL语言包括三种主要程序设计语言类别的语句:数据定义语言(DDL),数据操作语言(DML)及数据控制语言(DCL)。

  2.2数据库的简易流程(数据库客户端软件和数据库服务软件的执行流程)
Q: 安装时有一个客户端管理软件和一个服务器。 我们 平常操作的是客户端软件,发送脚本到服务器DMSM(数据库服务器),服务器分析和解析并展示执行结果。

  2.3主键的概念
Q:1.唯一的标识一行数据操作
2.可以作为其他表的外键来引用
3.业务主键:有意义(身份证号)
4.逻辑主键:唯一的意义就是标识一行 

  2.4业务主键,逻辑主键
Q:业务主键:有意义(身份证号)
逻辑主键:唯一的意义就是标识一行 (Guid)
  
  2.5主外键关系的概念以及使用
Q: 关系:两张表存在依赖数据时,就可以使用主外键来解决,其中将依赖列作为主键的就叫做:主键表;另一个就叫做外键表。外键表的外键列数据取自主键表的主键。
作用:
可以优化查询效率
减少数据冗余
维护方便
主外键约束:
为什么:为了避免两张表的主外键数据出现不一致的情况,需要建立主外键约束关系。
  
  2.6数据库的分离附加,脱机联机操作
Q:分离附加是脱离数据库管理系统的。 脱机联机就是暂时断开连接而已。
  
  2.7.1数据库的主要类型
Q:网状数据库、层次数据库和关系数据库

  2.7.2主要数据类型
Q :char类型,当储存的数据小于长度时,会自动用空格来补充。
Nchar类型,使用Unicode编码,任意字符(不管是数字还是字母)都占两个字节。
varchar类型,当储存的数据小于长度时,不会自动用空格来补充。(所以平常用varchar比较多,因为可以节约硬盘空间)
Nvarchar类型,类同,只不过用N就表示采用Unicode编码。
datetime类型,储存日期时间数据,如果要用代码类标识一个具体时间:‘2012-12-12’

  2.8使用SQL语句来创建数据库和表(知道有这回事,不要求掌握)
  2.9数据库的简单增删改查
  2.10约束:(会使用)
 2.10.1非空约束 null  / not null
 2.10.2主键约束 primary key
 2.10.3唯一约束 unique
 2.10.4默认约束 default
 2.10.5检查约束 check
 2.10.6外键约束  foreign key


代码创建主键:
-- Creating primary key on [Id] in table 'OperateType'
ALTER TABLE [dbo].[OperateType]
ADD CONSTRAINT [PK_OperateType]
PRIMARY KEY CLUSTERED ([Id] ASC);
GO


代码创建外键  
-- Creating foreign key on [Role_RoleId] in table 'RoleAction'
ALTER TABLE [dbo].[RoleAction]
ADD CONSTRAINT [FK_RoleAction_Role]
FOREIGN KEY ([Role_RoleId])
REFERENCES [dbo].[RoleInfo]
([RoleId])
ON DELETE NO ACTION ON UPDATE NO ACTION;
GO


3. 2-27知识点:(课程签名:SQL常见内置函数和关键字)
   3.1 top的使用
Q:1, Select top 2 * from teacher
  2, Select top 20 percent * from teacher  ------按百分比算行数,如果出现小数,则+1(类似天花板函数celling)
   
   3.2 Distinct的使用(去除重复数)
Q:1, Select distinct(age) from teacher -----求出不重复的age
2, Select distinct age,salary from teacher -----求出不重复的age和salary的组合(相当于将两个列的值加在一起的值不重复)

   3.3 聚合函数:
Q:注意事项:
1,聚合函数对NULL值不计算(直接忽略掉null值的行)
2,聚合函数的结果集是单个的值,没法与多个值的结果集集合
3,聚合函数可以与其他聚合函数的结果组合
4,不能整除
         小数列(被聚合的字段列是小数列):如果除出来是小数,则返回带小数的结果
         整数列(被聚合的字段列是整数列):如果除出来是小数,也是直接当整数算,不会自动+1

       3.3.1 Max
Q: 例子:SELECT max(UserId),UserId  from dbo.UserInfo GROUP BY UserId


       3.3.2 MIN
Q:例子:SELECT min(UserId),UserId  from dbo.UserInfo GROUP BY UserId

       3.3.3 AVG
Q:例子:SELECT avg(UserId),UserId  from dbo.UserInfo GROUP BY UserId

       3.3.4 SUM
Q:例子:SELECT sum(UserId),UserId  from dbo.UserInfo GROUP BY UserId

       3.3.5 COUNT
       Q:例子:SELECT COUNT(UserId),UserId  from dbo.UserInfo GROUP BY UserId

   3.4 between and  和 in 的使用
Q:例子:Select * from teacher where id  in (select id from Score where English>98 and Math> 98)

   3.5 like,  not like  通配符(%,_,[],^)
Q: _单个任意字符; 
      %任意长度任意字符;
  []代表取值范围内的单个字符;
  ^取非符号,必须和[]连用;
  例子:SELECT * FROM ActionGroupInfo WHERE ActionGroupName LIKE '[^45]%'

   3.6 空值处理:null 是什么?(记住这句话,就记住了所有的变换)
Q: 查询列中null的值用IS关键字(is null   /   is not null)
Select * from teacher where name is NULL
注意:要和ISNULL函数区别开来,如果第一个参数为null,则使用第二个参数作为返回值,否则,返回第一个参数   ISNULL(para1,para2)
例子:SELECT ISNULL (null ,'替换值')
   
   3.7 排序(order by id asc / desc)(默认是哪一种排序?)
Q: 排序--ORDER BY 子句要放到WHERE子句之后
ASC--升序(默认是升序)(显示的升序:ASC关键字)
例子:SELECT * FROM teacher ORDER by age ASC
DESC--降序
例子:SELECT *FROM teacher ORDER BY age DESC,id DESC
注意:多条件排序时,如上,当age中有相等的值,那么这些值按id降序

   3.8 分组(group by ),单条件分组,多条件分组(分组时,要注意的事情[位置,列])
Q: 1,--根据性别统计男女的人数
Select count(*) gender from teacher group by gender
--GROUP BY子句必须放到WHERE语句的之后,GROUP BY与ORDER BY 都是对筛选后的数据进行处理,而where是用来筛选数据的
2,--多条件分组
--分组条件,是age和gender列的组合,只有当age和gender一样的值时,才分为一组
Select count(*),age,gender from teacher group by age,gender
3,--分组一般要和聚合函数一起使用
强调:a,分组的结果是组信息,与表里的当行信息无关。
          b,一旦出现分组,前面要么是聚合函数,要么是分组的条件。


   3.9 筛选(Having的使用),它和where的区别
Q:要对分组后的结果再次进行筛选,就用having(与WHERE类似,都是筛选,只不过having是用来筛选分组后的组的)。
 having关键字必须用在Group  By 之后。
 错误例子:select * from dbo.UserInfo where COUNT(loginname)>1
 编译器报错信息:“聚合不应出现在 WHERE 子句中,除非该聚合位于 HAVING 子句或选择列表所包含的子查询中,并且要对其进行聚合的列是外部引用。”
   
   3.10 类型转换(CAST,CONVERT)
Q: 1,--CAST
      SELECT CAST(salary as INT)FROM teacher
2,--CONVERT
      SELECT CONVERT(int ,salary)FROM teacher

   3.11 数据库的导入导出功能

   3.12 union,union all
Q:首先,union就是用来合并结果集的
 用法注意:
1,要union的两个结果集的列数必须一样;
2,要连接的两个列的类型必须一致(或者类型兼容,比如varchar和nchar);
3,union默认去除了结果集中重复数据;
4,而union all 不会删除重复的数据;(因此,union all的效率要比union的效果高一些)

   3.13 一次插入多条数据
Q:方法一:Insert into userinfo select UserName, LoginCode, LoginPwd, Remark, SubDate, LastLoginDate, LastModifiedDate, LastLoginIP, DelFlag, UserStatus, Email, Phone, Sort, LoginErrorCount from userinfo
(注意:这种写法,1-2-4-8-16-32.......,这种方法适合快速插入测试数据,几何倍增。而且select的字段不能有ID,因为不能插入主键字段,所以不能select * ,而要写具体的列名)
      方法二:Select * into NewTable from userinfo  (一般用作表备份)
(注意:into的表名可以随便写,NewTable是不存在的,如果不存在则会自动创建这个表,而且新表不会有主键)

单独是赋值表结构的办法:
Select  Top 0 * into NewTable from userinfo ---- 这样就只复制了表结构。

   3.14 字符串函数
        3.14.1 LEN()
Q:Len返回的是去掉了尾部空格后的字符数(但是不计算末尾的空格)。例子:SELECT len(CName),CName  FROM dbo.Classes ---- 比如字段值是“你好a”,len的结果是 3

        3.14.2 datalength()
Q:返回的是包含尾部空格的字符串的字节数(计算所有空格的地方)。例子:SELECT datalength(CName),CName  FROM dbo.Classes ---- 比如字段值是“你好a”,datalength的结果是 5

        3.14.3 LOWER()
Q:转小写。例子:SELECT lower(CName),CName  FROM dbo.Classes ---比如字段值是“你好A”,lower的结果是 “你好a”

        3.14.4 UPPER()
Q:转大写。例子:SELECT upper(CName),CName  FROM dbo.Classes ---比如字段值是“你好b”,upper的结果是 “你好B”

        3.14.5 LTRIM()
Q:去除左边空格。SELECT ltrim(CName),CName  FROM dbo.Classes ---比如字段值是“    你好”,upper的结果是 “你好”

        3.14.6 RTRIM()
Q:去除右边空格。SELECT rtrim(CName),CName  FROM dbo.Classes ---比如字段值是“你好     ”,upper的结果是 “你好”

        3.14.7 LEFT()
Q:得到字符串从左边开始的指定个数的字符。SELECT left(CName,1),CName  FROM dbo.Classes ---比如字段值是“abc”,upper的结果是 “a”

        3.14.8 RIGHT()
Q:得到字符串从右边开始的指定个数的字符。SELECT left(CName,1),CName  FROM dbo.Classes ---比如字段值是“abc”,upper的结果是 “c”

        3.14.9 SUBSTRING(string,start,length) ---(原字符串,从哪开始截,截多长)
Q:从指定的位置截取固定长度的字符串。SELECT substring(CName,1,2),CName  FROM dbo.Classes ---比如字段值是“abc”,upper的结果是 “ab”


4. 2-29知识点(课程签名:ADO.NET)
   4.1 什么是ADO.NET
Q:这是一个广泛的类组,用于在以往的Microsoft技术中访问数据库的。是一组用于和数据源进行交互的面向对象类库。

   4.2 连接数据库的相关类:
Q:当问道ADO.NET相关的操作时,就要能顺口说出这几大类对象。
  4.2.1 SqlConnection
  4.2.2 SqlCommand
  4.2.3 SqlDataReader
  4.2.4 SqlDataAdapter
  4.2.5 SqlDataSet
  4.2.6 SqlParameter
  4.2.7 DataTable
   
   熟悉下面相关概念:
Q:Connection:主要是开启程序和数据库之间的连接。没有利用连接对象将数据库打开,是无
法从数据库中取得数据的。Close 和 Dispose 的区别,Close 以后还可以 Open,Dispose 以后
则不能再用。 

Command:(命令对象)主要可以用来对数据库发出一些指令,例如可以对数据库下达查询、新增、修
改、删除数据等指令,以及调用存在数据库中的存储过程等。这个对象是架构在 Connection 
对象上,也就是 Command 对象是透过连接到数据源。 

DataAdapter:(适配器) 主要是在数据源以及 DataSet 之间执行数据传输的工作(数据装配), 它可以透过 Command 
对象下达命令后,并将取得的数据放入 DataSet 对象中。这个对象是架构在 Command 对象
上,并提供了许多配合 DataSet 使用的功能。 

DataSet:这个对象可以视为一个暂存区(Cache) ,可以把从数据库中所查询到的数据保留
起来,甚至可以将整个数据库显示出来,DataSet 是放在内存中的。DataSet 的能力不只是可
以储存多个 Table 而已,还可以透过 DataAdapter 对象取得一些例如主键等的数据表结构,
并可以记录数据表间的关联。DataSet 对象可以说是 ADO.NET 中重量级的对象,这个对象
架构在 DataAdapter 对象上,本身不具备和数据源沟通的能力;也就是说 我们 是将
DataAdapter 对象当做 DataSet 对象以及数据源间传输数据的桥梁。DataSet 包含若干
DataTable、DataTableTable 包含若干 DataRow。 

DataReader:(数据读取器)当 我们 只需要循序的读取数据而不需要其它操作时,可以使用 DataReader 对
象。DataReader 对象只是一次一笔向下循序的读取数据源中的数据,这些数据是存在数据库
服务器中的,而不是一次性加载到程序的内存中的,只能(通过游标)读取当前行的数据,
而且这些数据是只读的,并不允许作其它的操作。因为 DataReader 在读取数据的时候限制
了每次只读取一笔,而且只能只读,所以使用起来不但节省资源而且效率很好。使用
DataReader 对象除了效率较好之外,因为不用把数据全部传回,故可以降低网络的负载。 
ADO.NET 使用 Connection 对象来连接数据库,使用 Command 或 DataAdapter 对象来执行
SQL 语句,并将执行的结果返回给 DataReader 或 DataAdapter ,然后再使用取得的
DataReader 或 DataAdapter 对象操作数据结果。
   
   4.3 数据库连接字符串
Q:server=.;database='dbName';uid=sa;pwd=123;

   4.4 SqlConnection类的State属性
Q:是判断数据库连接状态的一组枚举值。
注意:这里有一个连接池的概念---对连接对象的复用。(因为创建连接通道是比较消耗资源的,这是很宝贵的)

   4.5 SqlCommand类的方法:
ExecuteNonQuery()
Q:执行非查询语句(增、删、改),返回受影响函数。

ExecuteScalar()
Q:返回查询结果集的首行首列,是一个Object类型。

ExecuteReader()
Q:返回一个游标指针,然后用read()方法一行一行的读。性能很好。

   4.6 StatementCompleted事件的触发
Q:每条SQL语句执行完成后触发。

   4.7 获得刚刚插入数据库的自增id
Q : 方法一:string strSql="Insert into Student(name,age,cid) values ('{0}','{1}','{2}'); Select @@identity;"
 方法二:string strSql="Insert into Student(name,age,cid) output inserted.id values('{0}','{1}','{2}') "
 这两种方法都用cmd.ExcuteScalar()方法执行。
 注意:Select @@identity →是获得当前数据库连接中 最后一次 新增操作在数据库生成的自增长值

   4.8 Sql注入攻击(避免方式?)
Q:不要直接拼接SQL语句,采用参数话查询。如:SqlParameter(“@name”,“张三”),
   
   4.9 参数化查询


5. 3-1(课程签名:ADO.NET练习)
   5.1 打开文件选择框的类:OpenFileDialog以及判断用户是否点击确定
Q:例子:if(OpenFileDialog==DialogResult.OK)
{
......
}

   5.2 如何使用迭代生成树形菜单
Q:例子:public void BuildTree(TreeNode node, List<Category> list)
{
//获得父元素的ID
int pId = Convert.ToInt32(node.Tag);
foreach (Category model in list)
{
//找出集合中 父ID 和传入参数一致的
if (model.TParentId == pId)
{
//创建子节点
TreeNode sonNode = new TreeNode(model.TName);
//将子节点自己的ID存入 节点的 TAG中
sonNode.Tag = model.TId;
//将子节点 添加到父节点中
node.Nodes.Add(sonNode);
//迭代 调用(看看子节点还有没有子节点)
BuildTree(sonNode, list);
}
}


   5.3 文件读取类File,StreamReader的使用
Q: StreamReader reader = new StreamReader ("path",FileMode.OpenOrRead);
string[] lines = reader.ReadAllines();
foreach(string item in lines)
{
.......
}

5.4 大文件复制  
Q:例子:
using (FileStream fs = new FileStream(sourceFile, FileMode.Open))
{
//开辟缓冲区
byte[] byteArr = new byte[1024 * 1024];
using (FileStream fsWrite = new FileStream(destinationFile, FileMode.OpenOrCreate))
{
while (true)
{
//把读出来的字节数,写进缓冲区 返回读出来的字节数
int readCount = fs.Read(byteArr, 0, byteArr.Length);
//Encoding.Default.GetString();
fsWrite.Write(byteArr, 0, readCount);
if (readCount < byteArr.Length)
{
break;
}
}
}
                MessageBox.Show("OK");
            }


6. 3-2(课程签名:ADO.NET_SQL练习)
   6.1 单例模式(单例模式的创建)
Q: 保证在一个程序中某个对象只有一个实例。
步骤:1,关闭要实现单例模式的类的构造函数(私有化构造函数);
  2,在类中添加一个私有的类的静态变量;
  3,在类中添加一个共有的方法,返回当前的静态 变量,在方法中判断静态变量是否为null,如果为null则先new再返回,否则返回null。如果是在windform中,还要判断对象资源是否释放。
    注意:在多线程情况下,需要用lock块对其过程进行加锁,还有volatile关键字来标识。
例子:
public class Person
{
private static Person  _mySinglePerson= null;
private Person()
{
}

public static Person GetSingleInstance()
{
//在多线程情况下,需要 加锁
//这里:第一,直接锁当前的对象; 第二,定义一个线程 锁的标识volatile,然后锁住标识
lock(_mySinglePerson) 
{
if(_mySinglePerson == null || _mySinglePerson.IsDisPosed)
{
_mySinglePerson = new Person();
}
}
return _mySinglePerson;
}
}
 
   6.2 DataTable的使用
Q:例子:DataTable dt = new DataTable();
foreach(DataRow row in dt.Rows)
{
string str = row["columnName"].ToString();
....
}

   6.3 类SqlDataAdapter的使用(重点)
Q:Fill()方法
注意:SqlDataAdapter的内部还是使用了SqlDataReader去读取数据,只不过读取的过程被微软帮 我们 封装了而已

   6.4 类SqlCommandBuilder的使用(注意:他必须操作的是有主键的数据库)
Q:SqlCommandBuilder ---- 'sql命令生成助手---  一般不用 (注意:表必须有、主键,否则修改不了)
往里边传入一个DataAdapter对象,然后可以用相应方法直接执行对表的操作,使用相当简单,功能也很强大,
主要是微软为 我们 做了一系列封装,简化了程序员的操作(但一般 我们 都不使用这种方式对数据表进行操作)
例子:
//SQL命令生成助手(适配器)
SqlCommandBuilder scb=new SqlCommandBuilder(da);
//适配器在助手生成的SQL语句帮助下,成功的修改类数据库
da.Update(ds,"tempTable");
MessageBox.Show("修改成功");

   6.5 提取查询语句,封装SqlHelper类(不仅要会,而且要理解思想)


*难免有错误,如有,敬请指正。


请大家相信并坚持自己,一直走下去,等回头的时候,你会发现,你在别人眼中
,已经成功了。


----------------------------------------------------------------
何旭
1.简单SQL
1.1 T-SQL中的Switch语句
Q:case
第一种用法:直接对列进行值的判断,相当于程序中的Switch  取单个值
注意:then的值必须是同一种类型(因为列的类型只能有一个)
SELECT pId,
CASE pTypeId
WHEN 1 then '最爱'
WHEN 2 THEN '亲爱'
else '默认'
end,
pName,pCellPhone from PhoneNum


第二种用法,一般用来为列的取值范围,相当于,if else  取一个值的,取值范围
select sid,成绩={
CASE
when english between 90 and 100 THEN 'A'
when english <60 THAN 'E'
ELSE '缺考'
end  

from score

例子:select *,
(case TotalMoney
when TotalMoney>6000 then '金牌'
when TotalMoney>5000 then '银牌'
else '普通'
end) 
from table

1.2 T-SQL中的子查询
Q :在结果集的基础上,再次查询,
注意:一定以要给结果集取别名,否则会报错(取别名有两种方法:1,.....as  别名;  2,别名=(....))
例子:select * from (selec * from bc) as temp
select * from  temp = (selec * from bc) 

1.3 T-SQL中的Exists用法
Q:1.3.1 先执行 的是主查询,然后再执行子查询,将匹配行的数据显示出来
例子:select * from tbl where exists(select * from phonTYpe  where tbl.pId = phonType.pId)

1.3.2 判断结果集是否存在(效率低)
Q :例子:if exists(select * from tbl where ptId='001')
select 1
else 
select 2

1.4 T-SQL中的Any
Q: /*Any   or的意思*/
例子:select * from PhoneNum where pTypeId = any(select  pTypeId from b)
select * from PhoneNum where pTypeId = 1 or pTypeId = 2 .... 
注意:in/any/all关键字匹配结果集的时候,结果集只能有一个列
any相当于条件是很多个or
all相当于条件是很多个and
 
1.5 T-SQL中的All
Q:/*ALL    and的意思*/
例子:select * from PhoneNum where pTypeId = all(select pTypeId from b)
select * from PhoneNum where pTypeId = 1 and pTypeId = 2 .... 
ANY例子:
SELECT * from PhoneNum where pTypeId = any(select ptId from PhoneType)
ALL例子:
SELECT * from PhoneNum where pTypeId = all(select ptId from PhoneType)

2.SQL分页
2.1 SQL2008 微软官方推荐分页方式
Q:例子:select * from 
(
select ROW_NUMBER() over (order by ar_id) as rnum,* from Area
) as t
where runm between 10 and 14


3.SQL中表连接查询
3.1 等值连接(内连接) inner join
Q:任何一方都必须满足连接条件,如果有一方不满足连接条件就不显示
例子:select * from PhoneNum n inner join PhoneType t on n.pTypeId = t.ptId


3.2 左连接(左外连接) left join
Q:保证左边的数据都有,根据左边数据匹配
例子:select * from PhoneNum n left join PhoneType t on n.pTypeId = t.ptId


3.3 右连接(右外连接) right join
Q:保证右边的数据都有,根据右边数据匹配
例子:select * from PhoneNum n right join PhoneType t on n.pTypeId = t.ptId


3.4 交叉连接cross join(两张表的乘积)( 笛卡尔积)
Q :例子:select * from student cross join Score


3.5 全连接 full join(就是不管两边的表是否满足条件,全都显示,对方如果没有对应的数据,则显示null)
Q:左右两边的数据都进行匹配,相当于左连接和右连接相加。和inner join刚好相反
例子:select * from PhoneNum n full join PhoneType t on n.pTypeId = t.ptId


4. SQL进阶
4.1 SQL中变量
4.1.1 声明变量
declare @age int

4.1.2 变量赋值
set @age=3

4.1.3 声明并赋值
select @age = 29

4.1.4 如果表数据出现多行,则将最后一行的列赋值给变量(相当于循环赋值,自然取到最后一个值)
select @age=age from Student

4.1.5 输出变量的值
print @age

4.1.6 局部变量---先声明,再赋值
         全局变量---系统变量,系统已经定义好的,用户不能定义和修改,只能读取

5. SQL中的事务 (ACID特性:原子性,一致性,隔离性,持久性)
begin transaction 开始事务
rollback transaction 回滚事务(当事务中语句出现异常)
commit transaction 提交事务(更新数据)

银行事务转账列子:
declare @err int
set @err = 0
begin transaction 
begin
print '开始事务'
update bank set balance=balance-1000 where cid='0001'
set @err=@err+@@ERROR
update bank set balance=balance + 1000 where cid='0002'
set @err=@err+@@ERROR
if(@err>0)
begin
rollback transaction
print '回滚事务'
end
else
begin
commit transaction
print '提交事务'
end
end


6. SQL中存储过程
6.1 如何创建存储过程
例子:Create procedure usp_transferMoney
@intPerson varchar(20)
@outPerson varchar(20) '123' --可以给默认值,当参数有默认值的时候,执行的时候可以不传该参数
@abcPerson varchar(20)
as 
select @intPerson,@outPerson,@abcPerson

6.2 存储过程带输出参数
Create procedure usp_outPut
@maxEnglish int output
as
begin
select * from Score
select @maxEnglish = Max(English) from Score
end

declare @maxEnglish int
select @maxEnglish = 0
exec usp_outPut @maxEnglish output
print @maxEnglish


6.3 调用存储过程
exec usp_transferMoney --不带参数
exec usp_transferMoney ‘001’--带参数
exec usp_transferMoney @abcPerson='234'  --指定参数
注意:在执行存储过程的时候,如果带输出参数output,则在执行的时候必须显示执行,即加上“exec”


6.4 C#中如果参数是一个整型值,那么最好通过如下方式创建和赋值
SqlParameter p = new SqlParameter("@id",SqldbType.Int);  //注意:这里可以直接给参数的值,但是如果是0的话,就有个漏洞,它会默认认为是个枚举
p.Direction = ParameterDirection.OutPut;
return  p.value;


7. SQL中触发器
7.1 触发器定义
Q: (1)触发器是一种特殊的  存储过程
(2)触发器不能传参数,通过事件进行触发执行
例子:Create trigger tg_class on class--表名
AFTER--instead of(操作完成之前--替换语句)|after(操作完成之后)
INSERT --、instead、update、delete
AS
BEGIN
--触发器代码
end
Select * from inserted --保存了引发新增触发器的新增数据,只能在触发器中访问
--删除触发器
drop trigger tg_class

7.2 触发类型:
Q :(1)after和for是在  执行操作后  触发
(2)instead of 是  执行操作之前  触发(替换触发器),但是不会执行原语句


7.3 触发器触发条件:
Q:(1)update
(2)insert
(3)delete

7.4 触发器实例
---针对tbL_abc表的新增之后的触发器
Q:例子:Create Trigger triggerName on tbL_abc
after
insert 
as
begin
select * from inserted --保存了引发新增触发器的新增数据,只能在触发器中访问
end 


8. 索引
8.1 什么是索引
Q:就是为某个表,某个列建立一个查找目录
如果没有目录,汉语词典就要一页一页的翻。
有了目录直接翻目录,快速定位到查找位置。


8.2 索引类型(索引必须建立在某个列上面)
Q: (1):聚集索引(类似于字典的拼音目录):
数据的排列顺序,按照聚集索引排列(控制表的物理顺序)
因此每个表只能建立一个聚集索引
(当为某个字段建立聚集索引后,那么表的数据就会按照当前这个字段排序)
(2):非聚集索引(类似于字典的偏旁部首目录):
非聚集索引不会改变表的物理顺序(索引的存储顺序与实际的物理顺序无关)
每个表可以建立多个非聚集索引
(3):唯一索引
当为某个列建立唯一索引后,那么这列数据就不能有重复


9. 填充因子
Q:索引树的基本单位是索引页
填充因子  -----  就是为每页索引设置预留空间,
在将来加入新索引的时候,就只需要更新
当前索引页,而不需要更新索引树。填充因子就是指占用当前索引页的大小。


例如:如每页索引  2M  大小,当填充因子设置为60%,
那么每个索引页只存放2M*60%的数据,剩下2M*40%预留空间留给将来要加入索引项使用。


10. 临时表
Q:10.1 临时表是存在缓存中,而不是写在文件中,可以在系统数据库-->tempdb-->中查找
数据库连接断开,临时表就会自动清除。


10.2 局部临时表
Q:生命周期在当前会话,当前会话结束就销毁临时表
相当于C#的局部成员
创建时表名前加一个 ,#号
create table #tempUsers
(
id int identity(1,1),
name varchar(20)
)


10.3 全局临时表
Q:多个用户可以共享这个全局临时表
当所有会话都退出的时候,这个全局临时表才会被销毁
相当于C#的static 静态成员
创建时表名前加两个 ,##号
create table ##tempUsers
(
id int identity(1,1),
name varchar(20)
)


11. 三层结构
11.1 什么是三层结构.
Q:通常意义上的三层架构就是将整个业务应用划分为:表现层(UI)、业务逻辑层(BLL)、数据访问层(DAL)。


11.2 三层结构的目的
Q : 区分层次的目的即为了“高内聚,低耦合”的思想。

11.3 具体的三层是哪三层
Q:表现层(UI):通俗讲就是展现给用户的界面,即用户在使用一个系统的时候的所见所得。
业务逻辑层(BLL):针对具体问题的操作,也可以说是对数据层的操作,对数据业务逻辑处理。
数据访问层(DAL):该层所做事务直接操作数据库,针对数据的增添、删除、修改、更新、查找等每层之间

11.4 三层之间的关系
Q: 是一种垂直的关系。
三层结构是N 层结构的一种,一般来说,层次之间是向下依赖的,下层代码未确定其接口(契约)前,上层代码是无法开发的,下层代码接口(契约)的变化将使上层的代码一起变化。

11.5 三层结构的优缺点
Q: 优点: 分工明确,条理清晰,易于调试,而且具有可扩展性。
缺点: 增加成本。

12. 邮件发送
//邮件发送方法
Q:简单例子:
public void Send() {
//创建邮件对象
MailMessage mailMessage = new MailMessage();


//设置邮件字符集编码
mailMessage.SubjectEncoding = Encoding.Default;
mailMessage.BodyEncoding = Encoding.Default;
mailMessage.HeadersEncoding = Encoding.Default;


//设置邮件发件人
mailMessage.From = new MailAddress("abc@cilence.com");


//设置邮件收件人
mailMessage.To.Add(new MailAddress("cilence6788@cilence.com"));


//设置邮件主题
mailMessage.Subject = "主题";
//设置邮件正文
mailMessage.Body = "你好呀!";


//创建SMTP客户端
//SMTP服务端地址
SmtpClient smtpClient = new SmtpClient("127.0.0.1");
//SMTP客户端 通信凭证
smtpClient.Credentials = new NetworkCredential("abc@cilence.com", "123");
//发送
smtpClient.Send(mailMessage);
}


13. Excel导入导出
Q:常用的几种方式:
      1,OLE Automation (需要安装Excel。要启动excel进程,不适合服务器)
  2,Microsoft Jet  OleDb  (功能弱)
  3,Open XML
  4,NPOI  (不依赖Excel客户端,省资源,但只能处理.xls格式)
  
相关说明:ExecelHelper 类帮助说明
1.将对象集合导出到Excel + void ObjectCollectionsToExcel<T>(List<T> objectCollections, string path)
学要创建实体类对象集合,选中一个路径,导出即可


2.将Excel数据导入为对象集合 +List<T> ExcelToObjectCollections<T>(string path)


将Excel文档导入为ObjectCollection对象集合,是采用反射方式,去调用实体
类 构造函数  ,以下为实体类写法
重点在public Person(IRow row)构造函数


using NPOI.SS.UserModel;
namespace MyLibrary.Test
public class Person
{
public Person(IRow row) {
this.A = row.GetCell(0).ToString();
this.B = row.GetCell(0).ToString();
this.C = row.GetCell(0).ToString();
}


public string A { get; set; }
public string B { get; set; }
public string C { get; set; }
}




源代码例子:
using System;
using System.Collections.Generic;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using System.Reflection;
using System.IO;


namespace MyLibrary.Offices
{
public class ExcelHelper
{
#region 将对象集合导出到Excel + void ObjectCollectionsToExcel<T>(List<T> objectCollections, string path)
/// <summary>
/// 将对象集合导出到Excel
/// </summary>
/// <typeparam name="T">集合类型</typeparam>
/// <param name="objectCollections">集合对象</param>
/// <param name="path">导出路径</param>
public void ObjectCollectionsToExcel<T>(List<T> objectCollections, string path)
{
//判断对象集合是否为空,或者集合元素个数是否小于等于0
if (objectCollections == null || objectCollections.Count <= 0)
return;


//创建一个工作薄
HSSFWorkbook workbook = new HSSFWorkbook();
//创建一个表
ISheet sheet = workbook.CreateSheet();
sheet.SetColumnWidth(1, 100);


//声明行
IRow row;
//声明单元格
ICell cell;
//声明元素类型信息
Type type;
//声明元素属性集合
PropertyInfo[] propertyInfos;


//根据集合元素个数创建行
for (int i = 0; i < objectCollections.Count; i++)
{
//创建一行
row = sheet.CreateRow(i);
//取得元素类型信息
type = typeof(T);
//取得元素属性集合
propertyInfos = type.GetProperties();


//获取到当前对象
T currentObject = objectCollections[i];


//遍历元素属性
for (int j = 0; j < propertyInfos.Length; j++)
{
//创建一个单元格
cell = row.CreateCell(j);
//给单元格赋值
cell.SetCellValue(propertyInfos[j].GetValue(currentObject, null).ToString());
}
}


//创建数据流
using (FileStream stream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
//将数据流写入
workbook.Write(stream);
}
}
#endregion


#region 将Excel数据导入为对象集合 +List<T> ExcelToObjectCollections<T>(string path)
/// <summary>
/// 将Excel数据导入为对象集合
/// </summary>
/// <typeparam name="T">对象</typeparam>
/// <param name="path">Excel路径</param>
/// <returns>对象集合</returns>
public List<T> ExcelToObjectCollections<T>(string path)
{
//创建文件流读取Xls文件
using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
{
//创建Excel文档
HSSFWorkbook workbook = new HSSFWorkbook(fs);
//获取第一个表
ISheet sheet = workbook.GetSheetAt(0);
//获取最后一行的下标
int rowCount = sheet.LastRowNum;
//定义行
IRow row;
//获取T类型信息
Type type = typeof(T);
//定义List<T>泛型集合
List<T> list = new List<T>();


//遍历行集合
for (int i = 0; i <= rowCount; i++)
{
//取得行
row = sheet.GetRow(i);
//根据行信息,调用T对象最高级别构造函数
T t = (T)Activator.CreateInstance(type, row);
list.Add(t);
}
return list;
}

#endregion
}
}


------------------------------------------------------------
王兴 3月9日
1.MD5加密
Q:方法一:命名空间:System.Web.Security.HashPasswordForStoringInConfig
                     System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(strPwd,"MD5");
  方法二:  封装好的加密解密方法:
/// <summary>
/// 加密方法
/// </summary>
/// <param name="encryptString">要加密的字符串</param>
/// <returns>加密后的字符串</returns>
public  static  string EncryptString(string encryptString)
{
TripleDESEncryptor target = new TripleDESEncryptor("nihao");


return target.Encrypt(encryptString);


//string deCodeString = target.Decrypt(encodeString);
}


/// <summary>
/// 解密方法
/// </summary>
/// <param name="deEncryptString">要解密的字符串</param>
/// <returns>解密后的字符串</returns>
public  static string DeEncryptString(string deEncryptString)
{
TripleDESEncryptor target = new TripleDESEncryptor("nihao");
return target.Decrypt(deEncryptString);
}


public  static string GetMd5(string txt)
{
MD5Encryptor target = new MD5Encryptor(); // TODO: 初始化为适当的值
return target.GetMD5(txt);
}


2.读取数据库后,判断dataset里列的值是否为空
Q: Convert.IsDBNull(value);

if(dataset.Table[0]["columnName"]  != null)
{
.......
}

if (dr.IsNull(""))

.......
}

3.B/S , C/S
Q:B/S --- 浏览器服务器(Browser,Server)
  C/S --- 客户端服务器(Client,Server)
  
4.WebForm 的 Visible属性
Q:Visible 直接不生成html标签, 隐藏但占位置
  display:none是隐藏并且不占据位置,visibility:hidden;隐藏但占据位置


3月11日
1.可空值类型
Q:针对值类型的  在属性字段前面加上问号 “?”,  Nullable

非重点:
2.项目术语:CRM,OA,MIS,ERP
Q : CRM ---客户关系管理系统(Customer Relationship Management)
 OA--- 办公自动化 (Office Automation)
 MIS--- 信息管理系统(Management Information Systems)
 ERP---  企业资源计划系统 (Enterprise Resource Planning)
 
3.中文转拼音
Q :两种实现方式:
1,实时检索(但速度慢)
2,在DB中增加一个拼音字段(速度快,但有冗余),但必要的DB冗余是可以的,(以空间换时间)
3,通过网上别人封装好的汉语转拼音的静态方法类库
4,通过微软提供的汉语转拼音类库的方法(缺点:不能识别多音字)

5.邮件发送过程
Q: 理解是如何运作的原理。

6.C#发送邮件
Q: 见上面的简单例子.


3月12日
HTML部分:
1.静态页面 动态页面
2.URL:/   ../   ./   分别代表什么目录
Q:1,“/”表示网站的根目录(比如返回首页,加入层级很深,则用一个“/”)
  2,“../”表示当前文件夹的上一级文件夹
  3,“./”表示当前文件夹下(一个点加斜杠表示表示当前文件夹下,因此一般可以省略不写)
  4,“~/”表示
  5,“../../”表示当前文件夹的上一级的上一级(有几层则可以写几层)

3.设置缩略图可以用width,height吗
Q:不可以,因为只是改变了图片的长度和宽度,而图片的原始大小根本就没有改变, 而应该通过GDI去绘制一个缩略图。

3.有序列表,无序列表
Q: 有序列表--OL(orderList)
无序列表--UL(unorderList)

4.表格
Q:使用表格尽可能的使用标准的表格写法,加上Thead和Tbody
例子:<table>
<thead>
<tr>
<th>.....</th>
<tr>
</thead>
<tbody>
<tr>
<td>......</td>
</tr>
</tbody>
</table>

5.表单元素
Q :

6.input标签
Q:

7.select标签
Q:

8.textarea标签 label、fieldset标签
Q :

9.div span 及其区别
Q: span不换行
div会换行

10.CSS常见样式
Q:超链接的样式:a: hover,a:visited,a:active

11.样式选择器:
11.1 标签选择器
11.2 class选择器
11.3 标签+class选择器
11.4 id选择器
11.5 伪选择器
12.DIV+CSS布局


JS部分
13.变量与全局变量
Q:

14.判断变量是否初始化
Q:


3月14日
JS基础语法部分
1.函数的声明与匿名函数
2.JS的面向对象
3.String对象
4.Array对象
5.JS中的Dictionary
6.Array的简化声明
7.遍历数组: for, for-in


DOM部分
8.事件注册,动态设置事件
9.window对象:
9.1 alert方法,confirm方法
9.2 重新导航到指定的地址:navigate方法
9.3 setInterval,clearInterval,setTimeout


3月15日
1.Window对象
1.1 window.onload事件
1.2 location
1.3 window.event
1.4 history操作历史记录


2.document
2.1 write方法
2.2 getElementById getElementByName 
getElementByTagName
2.3 dom的动态创建 createElement


3月16日
1.DOM元素的innerText innerHTML
2.事件冒泡机制,如果阻止事件冒泡
3.事件中的this
4.修改元素的样式是设置class属性,className属性?
5.动态修改元素的样式
6.控制层的显示:style.display
7.元素样式的position:各种值的含义和效果
8.设置元素的宽
9.parseInt方法
10.js显示居中的DIV


11.form对象
11.1 submit()/onsubmit
11.2 不同浏览器js差异
11.3 表单默认的提交方式
11.4 表单JS提交方式
----------------------------------------------------------------------
第一部分:jquery


一、   查:当你想在页面中找到某个元素的时候,就要想到他们
↖(^ω^)↗  
1.1基本选择器:
Id选择器 ,Calss选择器,tag选择器,* ,组合选
择器
1.2层次选择器:
后代选择器,子代选择器,匹配选择器,~选择器
1.3节点遍历:
next(),nextAll(),prev(),prevAll(),siblings()
1.4过滤器:
:first,:last,:not,:even,:odd,:eq,:gt,:lt,
1.5属性过滤器:
$(“div[id]”),$(“div[title=text]”),
1.6表单对象过滤器:
#form1:enabled,#form1:disabled,input:checked,select 
option:select,
1.7表单选择器
:input,:text,:password……
二、修改:修改页面元素就用我吧 (*^__^*) 嘻嘻……
2.1jqury对象的方法
html(),val(),text(),css(),attr(),removeAttr()
2.2样式操作:
attr(),addClass(),removeClass(),toggleClass(),hasClass()
2.3复制节点:
clone(),clone(true)
2.4替换
replaceWith(),replaceAll(),wrap(),
三、新增:当你要新增元素时就用它们吧!O(∩_∩)O哈哈~ 
3.1创建Dom节点  例:$(“<a href=’#’>传智播客官网</a>”)
3.2 append(),appendTo()
3.3外部插入节点
after,before,insertAfter,insertBefore
四、删除:你不要 我们 了吗? ( ^_^ )/~~  拜拜
remove()
empty()
五、批量处理
5.1隐式迭代
5.2$.map,$.each
5.3元素的map和each
六、其他内容:
jquery动画
jquery cookie




第二部分:Dom补充
放在这里是不是有点莫名奇妙  (⊙_⊙?)
ChildNodes(NodeList类型-有序类数组对象),
length属性是实时的计算元素个数
insertBefore,appendChild,removeChild,replaceChild