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 in source.AsParallel().WithDegreeOfParallelism(50)select proc(x)).ToList();
 
十三 类和结构的异同?
类:类是引用类型在堆上分配,类的实例进行赋值只是复制了引用,都指向同一段实际对象分配的内存、类有构造和析构函数、类可以继承和被继承
结构:结构是值类型在栈上分配(虽然栈的访问速度比较堆要快,但栈的资源有限放),结构的赋值将分配产生一个新的对象、结构没有构造函数,但可以添加。结构没有析构函数、结构不可以继承自另一个结构或被继承,但和类一样可以继承自接口
结构体和类同样能够定义字段,方法和构造函数,都能实例化对象
 
十四 如何处理几十万并发数据?
1.用存储过程能分页就分页
2.第一次尽量过滤掉所有无用的数据
3.多线程 Thread
4.ajax异步处理
5.提高硬件。可以使用服务器集群。
6.缓存技术(硬件和程序两方面)。访问过的不需要二次访问数据库。
 
十五 方法参数修饰符ref和out的区别?

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

 

 

 

 

 

c#面试题(2)笔试题

上一篇:Flask 教程 第二十三章:应用程序编程接口(API)


下一篇:C#序列化与反序列化学习笔记