├── .gitattributes ├── .gitignore ├── CSharpInterviewBook └── Part1 │ ├── C#基础.md │ ├── GC与内存管理.md │ ├── SQL语法基础2.md │ ├── SQL语法基础(基于Sqlite).md │ ├── string.md │ ├── 多线程.md │ ├── 数据库原理.md │ ├── 面向对象基础1.md │ └── 面向对象基础2.md └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | [Xx]64/ 19 | [Xx]86/ 20 | [Bb]uild/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | 85 | # Visual Studio profiler 86 | *.psess 87 | *.vsp 88 | *.vspx 89 | *.sap 90 | 91 | # TFS 2012 Local Workspace 92 | $tf/ 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | *.DotSettings.user 101 | 102 | # JustCode is a .NET coding add-in 103 | .JustCode 104 | 105 | # TeamCity is a build add-in 106 | _TeamCity* 107 | 108 | # DotCover is a Code Coverage Tool 109 | *.dotCover 110 | 111 | # NCrunch 112 | _NCrunch_* 113 | .*crunch*.local.xml 114 | nCrunchTemp_* 115 | 116 | # MightyMoose 117 | *.mm.* 118 | AutoTest.Net/ 119 | 120 | # Web workbench (sass) 121 | .sass-cache/ 122 | 123 | # Installshield output folder 124 | [Ee]xpress/ 125 | 126 | # DocProject is a documentation generator add-in 127 | DocProject/buildhelp/ 128 | DocProject/Help/*.HxT 129 | DocProject/Help/*.HxC 130 | DocProject/Help/*.hhc 131 | DocProject/Help/*.hhk 132 | DocProject/Help/*.hhp 133 | DocProject/Help/Html2 134 | DocProject/Help/html 135 | 136 | # Click-Once directory 137 | publish/ 138 | 139 | # Publish Web Output 140 | *.[Pp]ublish.xml 141 | *.azurePubxml 142 | 143 | # TODO: Un-comment the next line if you do not want to checkin 144 | # your web deploy settings because they may include unencrypted 145 | # passwords 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # NuGet Packages 150 | *.nupkg 151 | # The packages folder can be ignored because of Package Restore 152 | **/packages/* 153 | # except build/, which is used as an MSBuild target. 154 | !**/packages/build/ 155 | # Uncomment if necessary however generally it will be regenerated when needed 156 | #!**/packages/repositories.config 157 | # NuGet v3's project.json files produces more ignoreable files 158 | *.nuget.props 159 | *.nuget.targets 160 | 161 | # Microsoft Azure Build Output 162 | csx/ 163 | *.build.csdef 164 | 165 | # Microsoft Azure Emulator 166 | ecf/ 167 | rcf/ 168 | 169 | # Windows Store app package directory 170 | AppPackages/ 171 | BundleArtifacts/ 172 | 173 | # Visual Studio cache files 174 | # files ending in .cache can be ignored 175 | *.[Cc]ache 176 | # but keep track of directories ending in .cache 177 | !*.[Cc]ache/ 178 | 179 | # Others 180 | ClientBin/ 181 | [Ss]tyle[Cc]op.* 182 | ~$* 183 | *~ 184 | *.dbmdl 185 | *.dbproj.schemaview 186 | *.pfx 187 | *.publishsettings 188 | node_modules/ 189 | orleans.codegen.cs 190 | 191 | # RIA/Silverlight projects 192 | Generated_Code/ 193 | 194 | # Backup & report files from converting an old project file 195 | # to a newer Visual Studio version. Backup files are not needed, 196 | # because we have git ;-) 197 | _UpgradeReport_Files/ 198 | Backup*/ 199 | UpgradeLog*.XML 200 | UpgradeLog*.htm 201 | 202 | # SQL Server files 203 | *.mdf 204 | *.ldf 205 | 206 | # Business Intelligence projects 207 | *.rdl.data 208 | *.bim.layout 209 | *.bim_*.settings 210 | 211 | # Microsoft Fakes 212 | FakesAssemblies/ 213 | 214 | # GhostDoc plugin setting file 215 | *.GhostDoc.xml 216 | 217 | # Node.js Tools for Visual Studio 218 | .ntvs_analysis.dat 219 | 220 | # Visual Studio 6 build log 221 | *.plg 222 | 223 | # Visual Studio 6 workspace options file 224 | *.opt 225 | 226 | # Visual Studio LightSwitch build output 227 | **/*.HTMLClient/GeneratedArtifacts 228 | **/*.DesktopClient/GeneratedArtifacts 229 | **/*.DesktopClient/ModelManifest.xml 230 | **/*.Server/GeneratedArtifacts 231 | **/*.Server/ModelManifest.xml 232 | _Pvt_Extensions 233 | 234 | # LightSwitch generated files 235 | GeneratedArtifacts/ 236 | ModelManifest.xml 237 | 238 | # Paket dependency manager 239 | .paket/paket.exe 240 | 241 | # FAKE - F# Make 242 | .fake/ 243 | /CSharpInterviewBook/Properties 244 | /CSharpInterviewBook/CSharpInterviewBook.csproj 245 | /CSharpInterviewBook.sln 246 | /README.md.bak 247 | -------------------------------------------------------------------------------- /CSharpInterviewBook/Part1/C#基础.md: -------------------------------------------------------------------------------- 1 | ### C#面试要点(1)值类型、引用类型、装箱与拆箱 2 | --- 3 | #### 值类型和引用类型的区别 4 | - **值类型** 5 | 6 | 描述 | 类型 7 | ---|--- 8 | 有符号整形 | int,short,long,sbyte 9 | 无符号整形 | uint,ushort,ulong,byte 10 | 浮点型 | float,double 11 | 字符型 | char 12 | 高精度小数 | decimal 13 | 布尔型 | bool 14 | 枚举 | enum 15 | 结构 | struct 16 | - **引用类型** 17 | 描述 | 类型 18 | ---|--- 19 | 类 | class,object,string 20 | 接口 | interface 21 | 数组 | 如int[],int[,] 22 | 委托 | delegate 23 | - **两者区别在于内存分配** 24 | 1. **栈**:线程栈,**存放值类型、引用类型在托管堆中的地址**,由操作系统管理,一个线程包含一个栈,栈中的值类型在其作用域结束后会被清理,效率很高。 25 | 2. **托管堆**:**存放引用类型**,托管堆中的对象由GC来管理和释放。 26 | - **值类型一直都存储在栈上面吗?所有的引用类型都存储在托管堆上面吗?** 27 | 1. 单独的值类型变量,如局部值类型变量都是存储在栈上面的; 28 | 2. 当值类型是自定义class的一个字段、属性时,它随引用类型存储在托管堆上,此时它是引用类型的一部分; 29 | 3. 所有的引用类型肯定都是存放在托管堆上的。 30 | 4. 结构体(值类型)中定义引用类型字段,结构体是存储在栈上,其引用变量字段只存储内存地址,指向堆中的引用实例。 31 | - **对象复制的差异** 32 | 将值类型的变量赋值给另一个变量(或者作为参数传递),会执行一次值复制。将引用类型的变量赋值给另一个引用类型的变量,它复制的值是引用对象的内存地址,因此赋值后就会多个变量指向同一个引用对象实例。 33 | 34 | --- 35 | #### out和ref关键字 36 | - out 和 ref都指示编译器传递参数地址,在行为上是相同的; 37 | - ref要求参数在使用之前要显式初始化,out要在方法内部初始化; 38 | - out 和 ref不可以用于重载,就是不能定义Method(ref int a)和Method(out int a)这样的重载,从编译角度看,二者的实质是相同的,只是使用时有区别; 39 | 40 | --- 41 | #### 装箱和拆箱 42 | - 值类型均隐式派生自System.ValueType。**只有值类型才有装箱、拆箱两个状态,而引用类型一直都在箱子里**。 43 | - **装箱即值类型转换为引用类型**,过程如下: 44 | 1. 在堆中申请内存,内存大小为值类型的大小,再加上额外固定空间(引用类型的标配:TypeHandle和同步索引块); 45 | 2. 将值类型的字段值拷贝新分配的内存中; 46 | 3. 返回新引用对象的地址 47 | - **拆箱即把装箱后的引用类型转换为值类型**,过程如下(以object转换为int为例): 48 | 1. 检查实例对象(object o)是否有效,如是否为null,其装箱的类型与拆箱的类型(int)是否一致,如检测不合法,抛出异常; 49 | 2. 指针返回,就是获取装箱对象(object o)中值类型字段值的地址; 50 | 3. 字段拷贝,把装箱对象(object o)中值类型字段值拷贝到栈上,意思就是创建一个新的值类型变量来存储拆箱后的值; 51 | - 性能损耗 52 | 1. **一般来说,装箱的性能开销更大**,装箱过程是需要创建一个新的引用类型对象实例,拆箱过程则需要创建一个值类型字段,开销更低。 53 | 2. **避免隐式装箱**,如下代码: 54 | 55 | ``` 56 | int i = 10; 57 | ArrayList list = new ArrayList(3); 58 | list.Add(i); 59 | ``` 60 | 查看Add方法的定义: 61 | 62 | ``` 63 | public virtual int Add(object value); 64 | ``` 65 | 可知list在执行Add方法时做了隐式拆箱,造成了性能的损耗。 66 | 67 | --- 68 | #### HashTable和Dictionary的区别 69 | - HashTable不支持泛型,而Dictionary支持泛型。比如Dictionary是一个泛型。 70 | - Hashtable的元素属于Object类型,存取值类型数据需要装箱拆箱,造成一定的性能损耗。 71 | - Hashtable 允许单线程写入, 多线程读取, 对 Hashtable 进一步调用 Synchronized() 方法可以获得完全线程安全的类型。而 Dictionary 非线程安全, 必须人为使用 lock 语句进行保护, 效率大减。 72 | 73 | 74 | -------------------------------------------------------------------------------- /CSharpInterviewBook/Part1/GC与内存管理.md: -------------------------------------------------------------------------------- 1 | ### GC与内存管理 2 | 3 | --- 4 | #### GC垃圾回收 5 | GC是垃圾回收(Garbage Collect)的缩写,是.NET核心机制的重要部分。它的基本工作原理就是遍历托管堆中的对象,标记哪些被使用对象(那些没人使用的就是所谓的垃圾),然后把可达对象转移到一个连续的地址空间(也叫压缩),其余的所有没用的对象内存被回收掉。 6 | 7 | --- 8 | #### 一个引用对象的生命周期 9 | - new创建对象并分配内存 10 | - 对象初始化 11 | - 对象操作、使用 12 | - 资源清理(非托管资源) 13 | - GC垃圾回收 14 | 15 | --- 16 | #### 非托管资源回收 17 | .NET中提供释放非托管资源的方式主要是:**Finalize()** 和 **Dispose()**。 18 | 19 | - Dispose需要手动调用,在.NET中有两中调用方式: 20 | 21 | ``` 22 | //方式1:显示接口调用 23 | SomeType st1=new SomeType(); 24 | //do sth 25 | st1.Dispose(); 26 | 27 | //方式2:using()语法调用,自动执行Dispose接口 28 | using (var st2 = new SomeType()) 29 | { 30 | //do sth 31 | } 32 | ``` 33 | 34 | - Finalize()可以确保非托管资源会被释放,但需要很多额外的工作(比如终结对象特殊管理),而且GC需要执行两次才会真正释放资源。听上去好像缺点很多,她唯一的优点就是不需要显示调用。 35 | 36 | --- 37 | #### using() 语法是如何确保对象资源被释放的? 38 | using() 只是一种语法形式,其本质还是try…finally的结构,可以保证Dispose始终会被执行。 39 | 40 | --- 41 | #### GC.Collect() 42 | 43 | 尽量不要手动执行垃圾回收的方法:GC.Collect()。垃圾回收的运行成本较高(涉及到了对象块的移动、遍历找到不再被使用的对象、很多状态变量的设置以及Finalize方法的调用等等),对性能影响也较大,因此我们在编写程序时,应该避免不必要的内存分配,也尽量减少或避免使用GC.Collect()来执行垃圾回收,一般GC会在最适合的时间进行垃圾回收。而且还需要注意的一点,在执行垃圾回收的时候,所有线程都是要被挂起的(如果回收的时候,代码还在执行,那对象状态就不稳定了,也没办法回收了)。 44 | 45 | --- 46 | #### GC在哪些情况下回进行回收工作? 47 | - 内存不足溢出时(0代对象充满时) 48 | - Windwos报告内存不足时,CLR会强制执行垃圾回收 49 | - CLR卸载AppDomian,GC回收所有 50 | - 调用GC.Collect 51 | - 其他情况,如主机拒绝分配内存,物理内存不足,超出短期存活代的存段门限 52 | 53 | --- 54 | #### .NET中的托管堆中是否可能出现内存泄露的现象? 55 | - 不正确的使用静态字段,导致大量数据无法被GC释放; 56 | - 没有正确执行Dispose(),非托管资源没有得到释放; 57 | - 不正确的使用终结器Finalize(),导致无法正常释放资源; 58 | - 其他不正确的引用,导致大量托管对象无法被GC释放; 59 | -------------------------------------------------------------------------------- /CSharpInterviewBook/Part1/SQL语法基础2.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caxich/CSharpInterviewBook/c3447c717558f3c05fe096b5e444cbae9e381bc0/CSharpInterviewBook/Part1/SQL语法基础2.md -------------------------------------------------------------------------------- /CSharpInterviewBook/Part1/SQL语法基础(基于Sqlite).md: -------------------------------------------------------------------------------- 1 | ### SQL语法基础 2 | 3 | --- 4 | #### 表结构 5 | 6 | ``` 7 | Student(ID,Name,Age,Sex) 学生表 8 | Course(ID,Name,TeacherID) 课程表 9 | Score(StudentID,CourseID,Score) 成绩表 10 | Teacher(ID,Name) 教师表 11 | ``` 12 | 13 | --- 14 | #### 查询语文(CourseID为1)比数学(CourseID为2)课程成绩高的所有学生的姓名 15 | 16 | 这是一个嵌套查询的题目,考察对子查询的使用,子查询结果作为一个集合可以当做一个独立的表来看待,子查询必须用括号括起来: 17 | 18 | ``` 19 | select st.[Name],c1.Score,c2.Score from 20 | (select sc.[Score], sc.StudentID from Score sc where sc.[CourseID]=1)c1, 21 | (select sc.[Score],sc.StudentID from Score sc where sc.[CourseID]=2)c2 22 | join Student st on st.[ID]= c1.[StudentID] 23 | where c1.[Score]>c2.[Score] and c1.[StudentID]==c2.[StudentID] 24 | ``` 25 | 26 | --- 27 | #### 查询平均成绩大于60分的同学的学号和平均成绩 28 | GROUP BY 语句用于结合合计函数,根据一个或多个列对结果集进行分组。GROUP BY子句在SELECT语句的WHERE子句之后并ORDER BY子句之前。WHERE 关键字无法与合计函数一起使用,**GROUP BY后面不能接WHERE条件,使用HAVING代替。** 29 | 30 | ``` 31 | select sc.[StudentID],avg(sc.Score) from Score sc 32 | group by sc.[CourseID] having avg(sc.Score)>60 33 | ``` 34 | 35 | --- 36 | #### 查询所有同学的学号、姓名、选课数、总成绩; 37 | 38 | ``` 39 | select st.[ID],st.Name,count(sc.CourseID),sum(sc.Score) from Student st 40 | left outer join Score sc on sc.[StudentID]=st.[ID] 41 | group by st.[ID] 42 | ``` 43 | 44 | --- 45 | #### 查询姓“张”的老师的个数 46 | 47 | ``` 48 | select count(t.ID) from Teacher t where t.Name like '张%' 49 | ``` 50 | > SQL LIKE子句使用通配符运算符比较相似的值。符合LIKE操作符配合使用2个通配符: 51 | > - 百分号 (%):百分号代表零个,一个或多个字符 52 | > - 下划线 (_):下划线表示单个数字或字符 53 | 54 | --- 55 | #### 找出教师表中姓名重复的数据,然后删除多余重复的记录,只留ID小的那个 56 | 57 | ``` 58 | select t.Name,count(t.Name) from Teacher t group by t.[Name] having count(t.Name)>1 59 | ``` 60 | 61 | 删除多余的记录,写这种稍微复杂一点的sql的时候,要学会拆解,此题可以拆解为三个部分(删除+重复数据+重复数据中ID最小的数据),先分别把3个部分的sql写了,然后再一步步合并,这样就轻松多了。 62 | 63 | 64 | ``` 65 | delete from Teacher where Name in 66 | (select t2.Name from Teacher t2 group by t2.[Name] having count(t2.Name)>1) 67 | and ID not in 68 | (select min(t3.ID) from Teacher t3 group by t3.Name having count(t3.Name)>1) 69 | ``` 70 | 71 | --- 72 | #### 按照成绩分段标示(<60不及格,60-80良,>80优),输出所有学生姓名、课程名、成绩、成绩分段标示 73 | 74 | 75 | ``` 76 | select st.Name,c.Name,sc.Score,(case 77 | when sc.Score > 80 then '优' 78 | when sc.Score < 60 then '不及格' 79 | else '良' end) as 'Remark' 80 | from Score sc 81 | inner join Student st on st.ID=sc.[StudentID] 82 | inner join Course c on c.ID=sc.[CourseID] 83 | ``` 84 | 输出结果: 85 | | st-Name | c-Name | sc-Score | Remark | 86 | | :---- | :---- | :---: | :---- | 87 | |张三 | 语文 | 50 | 不及格 | 88 | |李四 | 数学 | 96 | 优 | 89 | 90 | --- 91 | #### 查询所有课程成绩小于60分的同学的学号、姓名信息 92 | 这个比较简单,下面给出了两种方法,使用join链接和子查询: 93 | 94 | ``` 95 | select distinct st.* from Student st 96 | left join Score sc on sc.[StudentID]=st.ID 97 | where sc.[Score]<60 98 | -- -- 99 | select * FROM Student st WHERE st.ID in 100 | (SELECT s1.ID FROM Student s1,Score s2 WHERE s1.ID=s2.[StudentID] AND s2.Score<60) 101 | ``` 102 | 103 | --- 104 | #### 查询各科成绩最高和最低的分:以如下形式显示:课程名称,最高分,最低分 105 | 106 | ``` 107 | select c.Name as 课程,max(sc.Score) as 最高分,min(sc.Score) as 最低分 from Score sc 108 | left join Course c on c.ID=sc.[CourseID] 109 | group by sc.[CourseID] 110 | ``` 111 | 112 | --- 113 | #### 查询不同老师所教不同课程平均分从高到低显示 114 | 115 | ``` 116 | select t.Name,c.Name, avg(sc.Score) from Score sc,Teacher t,Course c 117 | where sc.[CourseID]=c.ID and c.TeacherID=t.ID 118 | group by sc.[CourseID] order by avg(sc.Score) desc 119 | ``` 120 | 121 | --- 122 | #### 查询和“1”号的同学学习的课程完全相同的其他同学学号和姓名 123 | 124 | ``` 125 | select s1.StudentID from Score s1 where s1.CourseID in(select s2.CourseID from Score s2 where s2.StudentID=1) 126 | group by s1.StudentID having count(*)=(select count(*) from Score s3 where s3.StudentID=1) 127 | ``` 128 | 129 | --- 130 | #### 查询选修“张老师”老师所授课程的学生中,成绩最高的学生姓名及其成绩 131 | 132 | 133 | ``` 134 | select t.Name,c.Name,s1.Score from Score s1,Teacher t,Course c 135 | where t.ID=c.[TeacherID] and s1.CourseID=c.ID and t.Name='张老师' 136 | and s1.Score=(select max(Score) from Score where CourseID=c.ID) 137 | ``` 138 | 139 | **注意:多表连接查询有多种写法,比如本题目中多表连接可以有以下两种方式:** 140 | 141 | ``` 142 | select t.Name,c.Name,s1.Score from Score s1,Teacher t,Course c where t.ID=c.[TeacherID] and s1.CourseID=c.ID 143 | -- 下面的写法和上面的效果是一样的! -- 144 | select t.Name,c.Name,s1.Score from Score s1 145 | join Teacher t on t.ID=c.[TeacherID] 146 | join Course c on s1.CourseID=c.ID 147 | ``` 148 | > **FROM TABLE1,TABLE2…效果等效于FROM TABLE1 join TABLE2…,都是内连接inner操作。** 149 | 150 | --- 151 | #### 查询所有成绩第二名到第四名的成绩 152 | 153 | 154 | ``` 155 | select s.[StudentID],s.Score from Score s order by s.Score desc limit 2 offset 2 156 | -- SQL 2005/2008中的分页函数是ROW_NUMBER() Over (Order by 列...)-- 157 | select t.[StudentID],t.Score from( 158 | select s2.[StudentID],s2.Score,ROW_NUMBER() OVER (ORDER BY s2.[Score]) AS rn from Score s2) t 159 | where t.rn>=2 and t.rn<=4 160 | ``` 161 | > 这是一个分页的题目,上面这是Sqlite提供的内置方法limite进行分页,不同数据库的分页方式又有些差别,但都大同小异。基本的过程都是先根据条件查询所需数据(加上行号),然后再此基础上返回指定行区间段的数据。 162 | 163 | --- 164 | #### 查询各科成绩前2名的记录:(不考虑成绩并列情况) 165 | 166 | 167 | ``` 168 | select * from Score s1 where s1.Score 169 | in(select s2.Score from Score s2 where s1.[CourseID]=s2.[CourseID] order by s2.Score desc limit 2 offset 0) 170 | order by s1.[CourseID],s1.[Score] desc 171 | -- 上面是sqlite中的语法,sqlite中没有top,使用limit代替,效果是一样的 -- 172 | select * from Score s1 where s1.Score 173 | in(select Top 2 s2.Score from Score s2 where s1.[CourseID]=s2.[CourseID] order by s2.Score desc) 174 | order by s1.[CourseID],s1.[Score] desc 175 | ``` 176 | -------------------------------------------------------------------------------- /CSharpInterviewBook/Part1/string.md: -------------------------------------------------------------------------------- 1 | ### string详解 2 | --- 3 | #### string类型 4 | - string为引用类型,其对象值存储在托管堆上。 5 | - string内部为一个char集合。string的长度就是char数组的个数 6 | - string的特性 7 | 1. **恒定性** 8 | - 字符串是不可变的,字符串一经创建,就不会改变,任何改变都会产生新的字符串。比如下面的代码: 9 | 10 | ``` 11 | string s1 = "a"; 12 | string s2 = s1 + "b"; 13 | ``` 14 | 执行上述代码会在堆上产生三个字符串实例:"a","b","ab"。 **字符串的一些操作函数,如str1.ToLower,Trim(),Remove(int startIndex, int count),ToUpper()等,都会产生新的字符串。** 15 | 2. **驻留性** 16 | 17 | - 相同的字符串在内存(堆)中只分配一次,第二次申请字符串时,发现已经有该字符串是,直接返回已有字符串的地址,这就是驻留的基本过程。 18 | 19 | --- 20 | 21 | #### StringBuilder类型 22 | - StringBuilder内部同string一样,有一个char[]字符数组,负责维护字符串内容。 23 | 24 | - **StringBuilder追加字符串的过程**: 25 | 1. StringBuilder的默认初始容量为16; 26 | 2. 使用stringBuilder.Append()追加一个字符串时,当字符数大于16,StringBuilder会自动申请一个更大的字符数组,一般是倍增; 27 | 3. 在新的字符数组分配完成后,将原字符数组中的字符复制到新字符数组中,原字符数组就被无情的抛弃了(会被GC回收); 28 | 4. 最后把需要追加的字符串追加到新字符数组中; 29 | - **StringBuilder产生新字符串的情况**: 30 | 1. 追加字符串时,当字符总长度超过了当前设置的容量Capacity,这个时候,会重新创建一个更大的字符数组,此时会涉及到分配新对象。 31 | 2. 调用StringBuilder.ToString(),创建新的字符串。 32 | 33 | 34 | >因此设置合适的初始容量是非常必要的,尽量减少内存申请和对象创建。因为StringBuilder本身是有一定的开销的,少量字符串就不推荐使用了,使用String.Concat和String.Join更合适。 35 | 36 | --- 37 | 38 | #### 算法题:字符串反转,例如:输入"12345", 输出"54321" 39 | - *解法1:* 40 | 41 | ``` 42 | public static string Reverse(string str) 43 | { 44 | if (string.IsNullOrEmpty(str)) 45 | { 46 | throw new ArgumentException("参数不合法"); 47 | } 48 | 49 | //注意:设置合适的初始长度,可以显著提高效率(避免了多次内存申请) 50 | StringBuilder sb = new StringBuilder(str.Length); 51 | for (int index = str.Length - 1; index >= 0; index--) 52 | { 53 | sb.Append(str[index]); 54 | } 55 | return sb.ToString(); 56 | } 57 | ``` 58 | - *解法2* 59 | 60 | ``` 61 | public static string Reverse(string str) 62 | { 63 | char[] arr = str.ToCharArray(); 64 | Array.Reverse(arr); 65 | return new string(arr); 66 | } 67 | ``` 68 | -------------------------------------------------------------------------------- /CSharpInterviewBook/Part1/多线程.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caxich/CSharpInterviewBook/c3447c717558f3c05fe096b5e444cbae9e381bc0/CSharpInterviewBook/Part1/多线程.md -------------------------------------------------------------------------------- /CSharpInterviewBook/Part1/数据库原理.md: -------------------------------------------------------------------------------- 1 | ### 数据库原理 2 | 3 | --- 4 | #### 索引的作用和它的优点缺点是什么? 5 | 索引就一种特殊的查询表,数据库的搜索引擎可以利用它加速对数据的检索。索引很类似与现实生活中书的目录,不需要查询整本书内容就可以找到想要的数据。缺点是它减慢了数据录入的速度,同时也增加了数据库的尺寸大小。 6 | 7 | --- 8 | #### 介绍存储过程基本概念和它的优缺点 9 | 存储过程是一个预编译的SQL语句,它的优点是允许模块化的设计,也就是说只需创建一次,在该程序中就可以调用多次。例如某次操作需要执行多次SQL,就可以把这个SQL做一个存储过程,因为存储过程是预编译的,所以使用存储过程比单纯SQL语句执行要快。缺点是可移植性差,交互性差。 10 | 11 | --- 12 | #### 使用索引有哪些需要注意的地方? 13 | - 创建索引的的字段尽量小,最好是数值,比如整形int等; 14 | - 对于频繁修改的字段,尽量不要创建索引,维护索引的成本很高,而且更容易产生索引碎片; 15 | - 定期的索引维护,如索引碎片的修复等; 16 | - 不要建立或维护不必要的重复索引,会增加修改数据(新增、修改、删除数据)的成本; 17 | - 使用唯一性高的字段创建索引,切不可在性别这样的低唯一性的字段上创建索引; 18 | - 在SQL语句中,尽量不要在Where条件中使用函数、运算符或表达式计算,会造成索引无法正常使用; 19 | - 应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描; 20 | - 应尽量避免在 where 子句中使用!=或<>操作符,否则将导致引擎放弃使用索引而进行全表扫描; 21 | 22 | --- 23 | #### 索引碎片是如何产生的?有什么危害?又该如何处理? 24 | - 索引在使用一段时间后(主要是新增、修改、删除数据,如果该页已经存储满了,就要进行页的拆分,频繁的拆分,会产生较多的索引碎片)会产生索引碎片。 25 | - 索引碎片会严重印象数据的查询效率,如果碎片太多,索引可能不会被使用。 26 | - **碎片的处理方式主要有两种:** 27 | 1. 第一种是预防:**设置页的填充因子** 28 | 意思就是在页上设置一段空白区域,在新增数据的时候,可以使用这段空白区域,可以一定的避免页的拆分,从而减少索引碎片的产生。 29 | 填充因子就是用来描述这种页中填充数据的一个比例,一般默认是100%填充的。如果我们修改填充因子为80%,那么页在存储数据时,就会剩余20%的剩余空间,这样在下次插入的时候就不会拆分页了。 那么是不是我们可以把填充因子设置低一点,留更多的剩余空间,不是很好嘛?当然也不好,填充因子设置的低,会需要分配更多的存储空间,叶子节点的深度会增加,这样是会影响查询效率的,因此,这是要根据实际情况而定的。 30 | 那么一般我们是怎么设置填充因子的呢,主要根据表的读写比例而定的。如果读的多,填充因子可以设置高一点,如100%,读写各一半,可以 80 ~ 90%;修改多可以设置50 ~ 70%。 31 | 2. 第二种是**索引修复**:定期对索引进行检查、维护,写一段SQL检查索引的碎片比例,如果碎片过多,进行碎片修复或重建,定期执行即可。具体可以参考本文末尾的相关参考资料。 32 | 33 | --- 34 | #### 锁的目的是什么? 35 | 主要解决多个用户同时对数据库的并发操作时会带来以下数据不一致的问题: 36 | - 丢失更新,同时修改一条数据 37 | - 读脏,A修改了数据后,B读取后A又取消了修改,B读脏 38 | - 不可重复读,A用户读取数据,随后B用户读取该数据并修改,此时A用户再读取数据时发现前后两次的值不一致 39 | - 还有一种是幻读,这个情况好像不多。 40 | 41 | 并发控制的主要方法是封锁,锁就是在一段时间内禁止用户做某些操作以避免产生数据不一致 42 | 43 | --- 44 | #### 锁的粒度有哪些? 45 | - 数据库锁:锁定整个数据库,这通常发生在整个数据库模式改变的时候。 46 | - 表锁:锁定整个表,这包含了与该表相关联的所有数据相关的对象,包括实际的数据行(每一行)以及与该表相关联的所有索引中的键。 47 | - 区段锁:锁定整个区段,因为一个区段由8页组成,所以区段锁定是指锁定控制了区段、控制了该区段内8个数据或索引页以及这8页中的所有数据行。 48 | - 页锁:锁定该页中的所有数据或索引键。 49 | - 行或行标识符:虽然从技术上,锁是放在行标识符上的,但是本质上,它锁定了整个数据行。 50 | 51 | --- 52 | #### 什么是事务?什么是锁? 53 | - 事务就是被绑定在一起作为一个逻辑工作单元的SQL语句分组,如果任何一个语句操作失败那么整个操作就被失败,以后操作就会回滚到操作前状态,或者是上个节点。为了确保要么执行,要么不执行,就可以使用事务。要将所有组语句作为事务考虑,就需要通过ACID测试,即原子性,一致性,隔离性和持久性。 54 | - 锁是实现事务的关键,锁可以保证事务的完整性和并发性。 55 | 56 | --- 57 | #### 视图的作用,视图可以更改么? 58 | - 视图是虚拟的表,与包含数据的表不一样,视图只包含使用时动态检索数据的查询;不包含任何列或数据。使用视图可以简化复杂的sql操作,隐藏具体的细节,保护数据;视图创建后,可以使用与表相同的方式利用它们。 59 | - 视图的目的在于简化检索,保护数据,并不用于更新。 60 | 61 | --- 62 | #### 什么是触发器(trigger)?触发器有什么作用? 63 | 触发器是数据库中由一定时间触发的特殊的存储过程,他不是由程序掉用也不是手工启动的。触发器的执行可以由对一个表的insert,delete, update等操作来触发,触发器经常用于加强数据的完整性约束和业务规则等等。 64 | 65 | --- 66 | #### SQL里面IN比较快还是EXISTS比较快? 67 | - 这个题不能一概而论,要根据具体情况来看。IN适合于外表大而内表小的情况;EXISTS适合于外表小而内表大的情况。 68 | - 如果查询语句使用了not in,那么对内外表都进行全表扫描,没有用到索引;而not exists的子查询依然能用到表上的索引。所以无论哪个表大,用not exists都比not in 要快。 69 | 70 | --- 71 | #### 维护数据库的完整性和一致性,你喜欢用触发器还是自写业务逻辑?为什么? 72 | 尽可能使用约束,如check、主键、外键、非空字段等来约束。这样做效率最高,也最方便。其次是使用触发器,这种方法可以保证,无论什么业务系统访问数据库都可以保证数据的完整新和一致性。最后考虑的是自写业务逻辑,但这样做麻烦,编程复杂,效率低下。 73 | -------------------------------------------------------------------------------- /CSharpInterviewBook/Part1/面向对象基础1.md: -------------------------------------------------------------------------------- 1 | ### 面向对象基础1 2 | --- 3 | #### 类型 4 | - 每一个类型(如System.Int32)在内存中都会有一个唯一的类型对象,通过GetType()可以获取该对象; 5 | - 类型对象(Object Type)存储在内存中一个独立的区域,叫加载堆(Load Heap),加载堆是在进程创建的时候创建的,不受GC垃圾回收管制,因此类型对象一经创建就不会被释放的,他的生命周期从AppDomain创建到结束; 6 | - 每个引用对象都包含两个附加成员:TypeHandle和同步索引块,其中TypeHandle就指向该对象对应的类型对象; 7 | - 类型对象的加载由class loader负责,在第一次使用前加载; 8 | - 类型中的静态字段就是存储在加载堆上,所以说静态字段是全局的,而且不会释放; 9 | --- 10 | #### 方法表 11 | - 方法表加载时父类在前子类在后,首先加载的是固定的4个来自System.Object的虚方法:ToString, Equals, GetHashCode, and Finalize; 12 | - 然后加载父类A的虚方法; 13 | - 加载自己的方法; 14 | - 最后是构造方法:静态构造函数.cctor(),对象构造函数.ctor(); 15 | --- 16 | #### .NET中的继承本质 17 | - 继承是可传递的,子类是对父类的扩展,必须继承父类方法,同时可以添加新方法。 18 | - 子类可以调用父类方法和字段,而父类不能调用子类方法和字段。 19 | - 子类不光继承父类的公有成员,也继承了私有成员,只是不可直接访问。 20 | - new关键字在虚方法继承中的阻断作用,中断某一虚方法的继承传递。 21 | - 执行就近原则:对于同名字段或者方法,编译器是按照其顺序查找来引用的,也就是首先访问离它创建最近的字段或者方法。 22 | --- 23 | #### 抽象类 24 | **基本特点:** 25 | - 抽象类使用Abstract声明,抽象方法也是用Abstract标示; 26 | - 抽象类不能被实例化; 27 | - 抽象类可以提供抽象方法,也可以提供非抽象方法;抽象方法必须定义在抽象类中; 28 | - 抽象类可以继承一个抽象类; 29 | - 抽象类不能被密封(不能使用sealed); 30 | - 同类Class一样,只支持单继承; 31 | --- 32 | #### 接口 33 | **基本特点:** 34 | - 接口使用interface声明; 35 | - 接口类似于抽象基类,不能直接实例化接口; 36 | - 接口中的方法都是抽象方法,不能有实现代码,实现接口的任何非抽象类型都必须实现接口的所有成员: 37 | - 接口成员是自动公开的,且不能包含任何访问修饰符。 38 | - 接口自身可从多个接口继承,类和结构可继承多个接口,但接口不能继承类。 39 | --- 40 | #### virtual、sealed、override和abstract的区别 41 | - virtual申明虚方法的关键字,说明该方法可以被重写 42 | - sealed说明该类不可被继承 43 | - override重写基类的方法 44 | - abstract申明抽象类和抽象方法的关键字,抽象方法不提供实现,由子类实现,抽象类不可实例化。 45 | --- 46 | #### 重载与覆盖的区别 47 | **重载**:当类包含两个名称相同但签名不同(方法名相同,参数列表不相同)的方法时发生方法重载。用方法重载来提供在语义上完成相同而功能不同的方法。 48 | **覆写**:在类的继承中使用,通过覆写子类方法可以改变父类虚方法的实现。 49 | -------------------------------------------------------------------------------- /CSharpInterviewBook/Part1/面向对象基础2.md: -------------------------------------------------------------------------------- 1 | ### 面向对象基础2 2 | --- 3 | #### const和readonly有什么区别 4 | - 初始化位置不同。const必须在声明的同时赋值;readonly即可以在声明处赋值,也可以在构造方法里赋值。 5 | - 修饰对象不同。const即可以修饰类的字段,也可以修饰局部变量;readonly只能修饰类的字段 。 6 | - const是编译时常量,在编译时确定该值,且值在编译时被内联到代码中;readonly是运行时常量,在运行时确定该值。 7 | - const默认是静态的;而readonly如果设置成静态需要显示声明 。 8 | - 支持的类型时不同,const只能修饰基元类型或值为null的其他引用类型;readonly可以是任何类型。 9 | --- 10 | #### 常量const有什么风险 11 | 12 | 常量的风险就是不支持跨程序集版本更新,常量值更新后,所有使用该常量的代码都必须重新编译。 13 | 14 | --- 15 | #### 静态成员和非静态成员的区别 16 | - 静态变量使用 static 修饰符进行声明,静态成员在加类的时候就被加载(静态字段是随类型对象存放在Load Heap上的),通过类进行访问。 17 | - 不带有static 修饰符声明的变量称做非静态变量,在对象被实例化时创建,通过对象进行访问 。 18 | - 一个类的所有实例的同一静态变量都是同一个值,同一个类的不同实例的同一非静态变量可以是不同的值 。 19 | - 静态函数的实现里不能使用非静态成员,如非静态变量、非静态函数等。 20 | 21 | --- 22 | #### 自动属性有什么风险 23 | 因为自动属性的私有字段是由编译器命名的,后期不宜随意修改,比如在序列化中会导致字段值丢失。 24 | 25 | --- 26 | #### 下面的代码输出什么结果 27 | 28 | ``` 29 | List acs = new List(5); 30 | for (int i = 0; i < 5; i++) 31 | { 32 | acs.Add(() => { Console.WriteLine(i); }); 33 | } 34 | acs.ForEach(ac => ac()); 35 | ``` 36 | 输出了 5 5 5 5 5,全是5!因为闭包中的共享变量i会被提升为委托对象的公共字段,生命周期延长了。 37 | 38 | --- 39 | #### 委托 40 | - C#中的委托都继承自System.Delegate类型; 41 | - 委托类型的声明与方法签名类似,有返回值和参数; 42 | - 委托是一种可以封装命名(或匿名)方法的引用类型,把方法当做指针传递,但委托是面向对象、类型安全的; 43 | - 事件可以理解为一种特殊的委托,事件内部是基于委托来实现的。 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CSharpInterviewBook 2 | ### C#相关面试知识点整理,搜集网络上各位前辈所分享的面试经验及知识点   3 | **整理来源:**   4 | - [.NET面试题解析](http://www.cnblogs.com/anding/p/5226343.html)  - [异步编程](https://www.cnblogs.com/jonins/p/9558275.html) 5 | ### 目录   6 | - [值类型、引用类型、装箱与拆箱](https://github.com/caxich/CSharpInterviewBook/blob/master/CSharpInterviewBook/Part1/C%23%E5%9F%BA%E7%A1%80.md) 7 | - [string详解](https://github.com/caxich/CSharpInterviewBook/blob/master/CSharpInterviewBook/Part1/string.md) 8 | - [面向对象基础1](https://github.com/caxich/CSharpInterviewBook/blob/master/CSharpInterviewBook/Part1/%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E5%9F%BA%E7%A1%801.md) 9 | - [面向对象基础2](https://github.com/caxich/CSharpInterviewBook/blob/master/CSharpInterviewBook/Part1/%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E5%9F%BA%E7%A1%802.md) 10 | - [GC与内存管理](https://github.com/caxich/CSharpInterviewBook/blob/master/CSharpInterviewBook/Part1/GC%E4%B8%8E%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.md) 11 | - [SQL语法基础(基于Sqlite)](https://github.com/caxich/CSharpInterviewBook/blob/master/CSharpInterviewBook/Part1/SQL%E8%AF%AD%E6%B3%95%E5%9F%BA%E7%A1%80%EF%BC%88%E5%9F%BA%E4%BA%8ESqlite%EF%BC%89.md) 12 | - [SQL语法基础2](https://github.com/caxich/CSharpInterviewBook/blob/master/CSharpInterviewBook/Part1/SQL%E8%AF%AD%E6%B3%95%E5%9F%BA%E7%A1%802.md) 13 | - [数据库原理](https://github.com/caxich/CSharpInterviewBook/blob/master/CSharpInterviewBook/Part1/%E6%95%B0%E6%8D%AE%E5%BA%93%E5%8E%9F%E7%90%86.md) 14 | - [多线程/异步编程详解](https://github.com/caxich/CSharpInterviewBook/blob/master/CSharpInterviewBook/Part1/%E5%A4%9A%E7%BA%BF%E7%A8%8B.md) 15 | --------------------------------------------------------------------------------