多项目开发
1.各个版本VS如何创建多项目,以及项目之间如何引用;
2.internal或者不写: 只有当前程序集内部可以访问
3.为什么要用配置文件。配置文件的读取:AppSettings。只有主项目(当前启动的项目)的config文件才起作用,config文件不能改名(控制台、winform中叫App.config,asp.net中叫web.config),不能建多个config,也不能建多个AppSettings段。
4、项目内部“转到定义”;看.Net内置的类转到定义怎么看不到代码?VS2012、2013、2015中自动using的不同方法。
5、调用第三方dll的方法(只能调用托管的dll)。自己的项目就用项目之间引用的方法;使用别人写好的dll就用直接添加dll引用的方法
索引器(*)
索引器:没有名字 ,索引器的内部本质 (ILSpy的IL模式下看)类型 this[参数]{get;set;}
可以是只读或者只写;
自己创建一个索引器,索引访问,键访问;
为什么字符串只能char ch = s[5];不能s[5]=‘a’。字符串不可变性;只读索引;
开发中自己写的机会很少,一道面试题:C#中索引器是否只能根据数字进行索引?是否允许多个索引器参数?
密闭类和静态类(*)
1、密闭类是修饰为sealed的类, sealed不能有子类。一般只有系统中的一些基本类声明为sealed。面试题:是否可以编写一个类继承自String类?
2、静态类:声明为static的类,不能实例化,只能定义static成员。
3、C#3.0特性:扩展方法。声明静态类,增加一个静态方法,第一个参数是被扩展类型的标记为this,然后在其他类中可以直接调用,本质上还是对静态方法调用提供的一个“语法糖”,也可以用普通静态方法的方式调用,所以不能访问private和protected成员。例子:给String扩展一个IsEmail方法。自己写的机会比较少。
浅拷贝、深拷贝
1、引用类型对象变量赋值的时候是指向同一个对象;
2、可以通过自顶一个拷贝方法复制出来一个新的对象;
3、如果对象之间有引用关系,如果拷贝的时候共享被引用的对象就是浅拷贝,如果被引用的对象也拷贝一份出来就是深拷贝。
结构体(*)
结构体(很少自己写):
一种值类型,拷贝副本。
对于结构,不像类那样存在继承。一个结构不能从另一个结构或类继承。但是,结构从基类 Object 继承。
struct Person
{
public int Age{get;set;}
public String Name { get; set; }
}
值类型、引用类型
什么是“引用类型”:引用类型派生自System.Object
什么是“值类型”:值类型均隐式派生自System.ValueType(ValueType其实也是继承自Object,不过是特立独行的一个分支)
值类型有哪些:数值类型(int、long、double、float、char)、bool、结构体、枚举。(怎么看不到Int32继承自ValueType)
引用类型有哪些字符串、数组、类、接口等
区别:
引用类型变量的赋值只复制对对象的引用;引用类型在堆内存(malloc);
值类型变量赋值会拷贝一个副本;值类型在栈内存;值类型一定是sealed;
CTS、CLS、CLR (*)
1、 .Net平台下不只有C#语言,还有VB.Net、F#等语言。IL是程序最终编译的可以执行的二进制代码(托管代码),不同的语言最终都编译成标准的IL(中间语言,MSIL);这样C#可以调用VB.Net写的程序集(Assembly,dll、exe)。在.Net平台下:不同语言之间可以互联互通、互相调用
2、不同语言中的数据类型各不相同,比如整数类型在VB.Net中是Integer、C#中是int。.Net平台规定了通用数据类型(CTS,Common Type System),各个语言编译器把自己语言的类型翻译成CTS中的类型。int是C#中的类型,Int32是CTS中的类型;int是C#的关键字,Int32不是。
3、不同语言的语法不一样,比如定义一个类A继承自B的C#语法是class A:B{},VB.Net的语法是Class A Inherits B。.Net平台规定了通用语言规范(CLS, Common Language Specification )
4、IL代码由公共语言运行时(CLR, Common Language Runtime )驱动运行,CLR提供了垃圾回收(GC, Garbage Collection,没有任何引用的对象可以被自动回收,分析什么时候可以被回收)、JIT(即时编译器);
5、值类型是放在“栈内存”中,引用类型放到“堆内存”,栈内存会方法结束后自动释放,“堆内存”则需要GC来回收。
拆箱和装箱box、unbox(*)
值类型赋值给Object类型变量的时候,会发生装箱:包装成Object。ValueType不也是继承自Object吗(CLR内部处理)
Object类型变量赋值给值类型赋值的时候会发生拆箱,需要做显式转换。
*拆箱的时候一定要用装箱的类型
Equals方法
查看判断两个对象是否是同一个对象要用:object.ReferenceEquals();
为什么两个对象内容一样,==还是false?
Object的Equals方法也比较两个变量指向的是否同一个对象;对象如果override 了Equals方法,就可以进行内容的相同比较。
默认情况下==不是调用Equals方法,需要重载==运算符;
String等这些类是重写了Equals方法。
字符串暂存池(缓冲池)
字符串不可变性,字符串的‘暂存池’两个特性
字符串是引用类型,程序中会存在大量的字符串对象,如果每次都创建一个字符串对象,会比较浪费内存、性能低,因此CLR做了“暂存池”(拘留池,缓冲池,暂存池),在一些情况下对于字符串对象进行了重用。
ref与out
普通参数是“值类型传递拷贝,引用类型传递引用”,但是都不能在函数内部修改外部变量的指向(p.Age=5不是可以吗?),这时候要用ref或者out(相当于把变量都传进去了),他们的作用不同:ref的作用“方法内部修改外部变量的引用”;out的作用“方法内部给外部变量初始化,相当于一个函数多个返回值”。
1、使用ref型参数时,传入的参数必须先被初始化,方法中可以不赋值。对out而言,必须在方法中对其完成初始化,方法外部不用初始化,初始化也没用。
2、使用ref和out时,在方法的参数和执行方法时,都要加ref或out关键字。以满足匹配。
3、out适合用在需要retrun多个返回值的地方,而ref则用在需要被调用的方法修改调用者的引用的时候。
应用: 1、交换两个变量的值; 2、int.TryParse():if(int.TryParse(s,out i)),返回值表示是否转换成功,out参数表示转换成功的值。