c#面试题(2)笔试题
一 .怎么样在多线程中调用同一对象,前提是该对象每分钟会被某一线程改写一次,改写过程中其他线程暂停访问,待改写完成后再进行访问?(这个不会。。。,有请大神指教)
二.将List<ClassA> lst 中的所有元素复制给另一List<ClassA> lst2 对象,有几种方法?引用复制后使用lst2会出现什么问题?
List<T>对象中的T是值类型的情况(int 类型等)
对于值类型的List直接用以下方法就可以复制:
List<T> oldList =new List<T>(); oldList.Add(..); List<T> newList =new List<T>(oldList);
List<T>对象中的T是引用类型的情况(例如自定义的实体类)
1、对于引用类型的List无法用以上方法进行复制,只会复制List中对象的引用,可以用以下扩展方法复制:
staticclass Extensions { publicstatic IList<T> Clone<T>(this IList<T> listToClone) where T: ICloneable { return listToClone.Select(item => (T)item.Clone()).ToList(); } //<span style="color: rgb(0, 0, 0);">当然前题是List中的对象要实现ICloneable接口</span> }
2、另一种用序列化的方式对引用对象完成深拷贝,此种方法最可靠
publicstatic T Clone<T>(T RealObject) { using (Stream objectStream = new MemoryStream()) { //利用 System.Runtime.Serialization序列化与反序列化完成引用对象的复制 IFormatter formatter =new BinaryFormatter(); formatter.Serialize(objectStream, RealObject); objectStream.Seek(0, SeekOrigin.Begin); return (T)formatter.Deserialize(objectStream); } }
3、利用System.Xml.Serialization来实现序列化与反序列化
publicstatic T Clone<T>(T RealObject) { using(Stream stream=new MemoryStream()) { XmlSerializer serializer =new XmlSerializer(typeof(T)); serializer.Serialize(stream, RealObject); stream.Seek(0, SeekOrigin.Begin); return (T)serializer.Deserialize(stream); } }
三 WebAPI和WebService的区别
webapi用的是http协议,webservice用的是soap协议
webapi无状态,相对webservice更轻量级。webapi支持如get,post等http操作
四 三层架构是哪三层?各自干什么?有什么优缺点?
三层架构一般包含:控制层,业务逻辑层,数据访问层。
1.数据库访问层(DAL)仅提供对数据库的CRUD(增删改查)操作,而不管操作后的结果,也不管逻辑过程(譬如同名用户,不合法用户名)。
2.业务逻辑层(BLL)不会直接与数据库交互,他与数据库的交互是通过DAL提供的方法。在调用这些方法前,要加入自己的逻辑判断或者业务处理。另外业务逻辑层(BLL)还有可能不会去调用DAL层的方法,而是进行其他业务处理。
3.用户界面层(UI)层是不会调用DAL层的,他只调用BLL层提供的方法,再由BLL层自己决定是否继续调用DAL层。
优点:
1.层次清晰,每个层次都提供了接口定义
2.很容易用新的实现替换原来的层次实现。例如对sql进行性能优化,并不会影响其他层的代码结构。有利于后期维护。
3.有利于实现切面编程,减轻业务的复杂程度,加快编码效率。
4. 每个层次的定位明晰,业务处理的内容明确。依据层次,可以划分不同的分工。开发人员可以只关注整个结构的其中某一层。
5.接口定义也提供了良好的可扩展性。例如数据库从mysql切换到oracle,只需要通过配置来切换。
6.降低了代码之间,层与层的依赖关系
7. 复用性:利于各层代码逻辑的复用
8.安全性:接口设计需要符合对扩展开发,对修改关闭的原则,增强了系统的安全性
缺点
1.降低了系统的性能。使用中间层访问数据库,对数据进行转换等等都需要计算时间。
2.新增业务处理时,需要在各个层增加功能。
3. 不同的层次对接口规范理解的层次不一样,对接口维护,调用,监控都会产生影响
4.当用户访问量增大时,性能会遇到瓶颈。
5 部署会造成服务中断
6.服务挂了之后,需要人工及时的处理,给用户和公司带来损失
五 EF(EntityFramework)和ADO.NET 的对比
1.性能上(运行效率)Ado.Net的性能更高些,直接使用SQLHelper的Command、Connection等命令通过写SQL语句对数据库进行操作。(EF的实体模型,性能上肯定要损失些!!)
2.方便性上(开发效率)EF使用起来更方便,原因是开发人员不用关心如何访问数据库了。
3.适用性上:EF适合较大型的项目,数据量也较大些;而Ado.Net适用于小型项目(执行效率高些)。
4.灵活性上Ado.Net灵活性更高,但可能存在sql注入的问题。
EF最终都是翻译转换成sql去执行的,开发很快捷。ado相对来说你可以自行处理sql存储过程和脚本,灵活性大,不需要进行翻译,但工作量会相对多一些。
微软最初退出ORM技术,目的是在提高开发效率,并不是提高运行效率,它只是使对数据库的编码更符合面向对象的编程的方式。
EF框架和Ado.Net,其实简单来说,就是封装和原生的PK了
六 get 和post 的区别
1.GET是从服务器上获取数据,POST是向服务器传送数据。
2.在客户端, GET方式在通过URL提交数据,数据在URL中可以看到;POST方式,数据放置在HTML HEADER内提交
3.对于GET方式,服务器端用Request.QueryString获取变量的值,对于POST方式,服务器端用Request.Form获取提交的数据。
4.GET方式提交的数据最多只能有1024字节,而POST则没有此限制
5.安全性问题。正如在(2)中提到,使用 GET 的时候,参数会显示在地址栏上,而 POST 不会。所以,如果这些数据是中文数据而且是非敏感数据,那么使用 GET ;如果用户输入的数据不是中文字符而且包含敏感数据,那么还是使用 POST为好
七 DataSet 和DataTable 的区别?
DataSet是数据集,DataTable是数据表,DataSet存储多个DataTable。DataSet和DataTable像是专门存储数据的一个容器,在你查询数据库得到一些结果时可以存在里面。
八 string 和stringBuilder的区别?
stringbuilder相对于string,效率要高些,string会在每次改变的时候进行内存重新组合,而stringbuilder则不会从新组合,另外stringbuilder有append,insert,replace 等一些方法,用起来比较方便。
九 在开发过程中是否用过设计模式?列举几种?
工厂模式、抽象工厂模式、单例模式、观察者模式、发布-订阅模式等
十 foreach继承于哪个接口?是否必须继承该接口? 必须实现了IEnumable接口
十一 EF 实现分页,批量插入数据那个最高效?
.skip(PageSize *PageIndex).take(PageSize) PageSize是每页的大小、PageIndex是当前的页数 , 批量插入BulkInsert
十二 如何使用AsParallel?如何使用AsQueryable?
var
result = (
from
x
in
source.AsParallel().WithDegreeOfParallelism(50)
select
proc(x)).ToList();
2.第一次尽量过滤掉所有无用的数据
3.多线程 Thread
4.ajax异步处理
5.提高硬件。可以使用服务器集群。
6.缓存技术(硬件和程序两方面)。访问过的不需要二次访问数据库。
1)out和ref传变量的地址(引用地址),形参改变,实参也改变。因为他们都是引用一个地址的;
2)带ref和out修饰的参数只能传递变量不能传递常量.
3)out和ref的区别
out修饰的参数必须在方法内修改,而ref可以修改也可以不修改;
out在传入参数的时候,参数是局部变量的话,可以不用赋值,因为out一定会对其进行赋值;
而ref修饰的参数,在实参必须有初始值才能调用。因为ref修饰的不一定会给它赋值。
十六 堆和栈的区别?
1.申请方式不同,栈系统自动分配,堆人为申请开辟
2.大小不同,栈空间较小,堆空间较大
3.申请效率不同,栈速度快,堆比较慢
4.存储内容不同,栈在函数调用时,先是函数地址,然后是参数,静参不入,堆是人为安排
5.底层不同,栈是连续的空间,堆是不连续的空间
十七 谈谈final,finally,finalize的区别
final 可以用来修饰类、方法、变量,分别有不同的意义,final 修饰的 class 代表不可以继承扩展,final 的变量是不可以修改的,而 final 的方法也是不可以重写的(override)。
finally 则是 Java 保证重点代码一定要被执行的一种机制。我们可以使用 try-finally 或者 try-catch-finally 来进行类似关闭 JDBC 连接、保证 unlock 锁等动作。
finalize 是基础类 Object 的一个方法,它的设计目的是保证对象在被垃圾收集前完成特定资源的回收。
十八 使用双检索实现一个单例模式Singleton
public class SingletonClass { private static readonly object _lock = new object(); private static volatile SingletonClass _instance; public static SingletonClass Instance { get { if (_instance == null) { lock (_lock) { if (_instance == null) { _instance = new SingletonClass(); } } } return _instance; } } private SingletonClass() { //your constructor } }
十九 请输出程序结果
static void Main(string[] args) { int x = 20; int y = 40; GetPlus( x, y); Console.WriteLine("x=" + x + "y=" + y); } public static void GetPlus( int x,int y) { x = x + y; y = x + y; }
//x=60 y=40 ref引用的指参数值改变,而y参数的值不变
static void Main(string[] args) { Person p1 = new Person(); Employee p2 = new Employee(); Person p3 = new Employee(); Employee p4 = p3 as Employee; p1.Foo(); p1.Act(); p2.Foo(); p2.Act(); p3.Foo(); p3.Act(); p4.Foo(); p4.Act(); } } public class Person { public void Foo() { Console.WriteLine("f1"); } public virtual void Act() { Console.WriteLine("a1"); } } public class Employee : Person { public void Foo() { Console.WriteLine("f2"); } public override void Act() { Console.WriteLine("a2"); } }
// f1
// a1
// f2
// a2
// f1
// a2 p3的Acr被重写
// f2 p4就是Employee对象
// a2
static void Main(string[] args) { string a = "t1"; Foo(a); Console.WriteLine(a); } static void Foo(string x) { string y = "t2"; x = y; }
// t1
int x = 3 << 1; int y = 1 << 2; int z = x ^ y; Console.WriteLine(x); Console.WriteLine(y); Console.WriteLine(z); // 6 // 4 // 2
static void Main(string[] args) { A a = new B(); a.Fun(); } public abstract class A { public A() { Console.WriteLine('A'); } public virtual void Fun() { Console.WriteLine("A.Fun()"); } } public class B : A { public B() { Console.WriteLine('B'); } public new void Fun() { Console.WriteLine("B.Fun()"); } } // A // B // A.Fun()
int i = 2000; object o = i; i = 2001; int j = (int)o; Console.WriteLine("i={0},o={1},j={2}", i, o, j); // i=2001,o=2000,j=2000
十九 查询每门课都大于80分的学生姓名
select distinct name from grade where name not in (select distinct name from grade where fenshu <= 80)
select name from grade group by name having min(fenshu)>80
create table grade(
name nvarchar(10),
kecheng nvarchar(10),
fenshu int
)
二十 删除冗余信息
Delete From Student Where Id Not In(Select Min(Id) From Student Group by Name,kechengid,kechengname,fenshu)
create table student (
id bigint identity(1,1) not null PRIMARY key,
Number int,
name nvarchar(10),
kechengid int,
kechengname nvarchar(10),
fenshu int
)
二十一
year month amount
1991 1 1.1
1991 2 1.2
1991 3 1.3
1991 4 1.4
1992 1 2.1
1992 2 2.2
1992 3 2.3
1992 4 2.4
查成这样一个结果
year m1 m2 m3 m4
1991 1.1 1.2 1.3 1.4
1992 2.1 2.2 2.3 2.4
select year, max(case month when 1 then amount else 0 end) as 'm1', max(case month when 2 then amount else 0 end) as 'm2',
max(case month when 3 then amount else 0 end) as 'm3',
max(case month when 4 then amount else 0 end) as 'm4'
from test group by year
二十二 一个叫 team 的表,里面只有一个字段name, 一共有4 条纪录,分别是a,b,c,d, 对应四个球队,现在四个球队进行比赛,用一条sql 语句显示所有可能的比赛组合.
select * from team a,team b where a.name>b.name;
二十三
有以下两张表,
Class表
classid classname
1 高三(一)班
2 高三(二)班
3 高三(三)班
Student表
studentid studentName classid
1 张三 2
2 李四 1
3 王五 1
4 赵六 3
5 钱七 2
6 孙九 3
score表
scoreid course studentid score
1 数学 2 99
2 数学 3 60
3 数学 4 80
4 语文 5 79
5 语文 6 58
6 语文 1 66
7 英语 6 76
8 英语 4 87
9 英语 3 100
10 英语 2 69
编写SQL语句查询出每个各科班分数最高的同学的名字,班级名称,课程名称,分数
select t.classname,course,max(score) 'score',min(t.studentName) 'studentName' from (select s.studentName,c.classname,r.course,r.score from student s inner join class c on s.classid=c.classid inner join score r on r.studentid=s.studentid ) as t group by classname,course
二十四 (没有答案,有兴趣的可以自己建表测试)
有三个表,结构如下:
STUDENT(学生证号,姓名,性别,出生年月)
COURSE(课程号,课程名,授课教师)
SC(学生证号,课程号,成绩,授课教师)
用标准 SQL 语句完成下列操作
1. 查询女生的基本情况,并按照学生证号降序排列
2. 查询成绩在 90分以上的学生的姓名
3. 查询数学类课程的课程号和课程名(模糊查询,以 S开头)
4. 查询选课学生所选课程的课程号和成绩,以及该学生的姓名和性别
5. 查询 03号课程的平均成绩
6. 删除成绩不及格的学生姓名
7. 把学生证号为 90876的学生所选的 01号课程成绩改为 80分