.NET总结

从事.Net工作以来,大大小小的面试也有N多次了,现在把一些常见的面试问题做个总结,也希望能帮到即将要面试的同行们吧。

1、你先作个自我介绍吧?

2、你做过哪些项目,具体负责哪些模块?

3、你带过团队,你是怎么管理团队的?

 

你对mvc的了解有多少?面试官有可能会从以下几个问你:

啥是mvc?为什么要采用mvc框架进行开发?

mvc将系统分解成实体模型、视图、控制器三部分,每一部分相对独立,职责单一,就是通过把职责、性质相近的成分归结在一起,不相近进行隔离,在实现过程中专注于自身的核心逻辑

描述下mvc的路由机制以及生命周期?

1、当网站第一次启动的时候,RouteTable把URL映射到Handle

2、在发起请求的时候,UrlRoutingModule接收到请求,循环调用其RouteCollection集合中的RouteBase对象,找出匹配的RouteBase。

3、根据匹配的RouteBase对象返回的RoueData对象,获取RouteHandler。

5.、如果RouteHandler为MvcRouteHandler,并且其返回的HTTP处理程序为MvcHandler,则进入到MVC框架

6、MvcHandler对象负责创建控制器,并且把控制器传入ControllerContext,然后执行控制器。

7、控制器检测要执行的控制器方法,构建参数列表并且执行方法。

8、控制器方法调用RenderView()来把内容呈现回浏览器。Controller.RenderView()方法把这个工作委托给某个ViewEngine来做。

简单说下url和mvc路由有什么区别?

 

控制器和视图的传值方式有哪几种?各自有什么区别

 

EF Code First

1、在EF框架中你是如何实现的?

答:继承DbContext

2、EF事务你是怎么处理的?

using (var transactionScope = new TransactionScope(TransactionScopeOption.Suppress)) 
{ //ADO... transactionScope.Complete(); }

3、EF的性能如何调优?

1) 分清真分页和假分页

//假分页:把数据放到内存中,转换成list后,从list进行分页操作
query.ToList().Skip((PageIndex - 1) * PageSize).Take(PageSize);

//真分页
query.Skip((PageIndex - 1) * PageSize).Take(PageSize).ToList();

2) 合理使用EF加载方式:

  延时加载(惰性加载):当主表数据量过大时,频繁访问数据据会降低性能。Configuration.LazyLoadingEnabled = false

  预加载(贪婪加载):只要访问一次数据库只可以拿到数据放到内存中,但数据量很多,或实体级联关系复杂时就要关注性能了。var q = from t in dbcontext.Customer.Include("Order") select t;

  显式加载:添加判断条件,直接过滤那些无用数据从而尽量减少与数据库交互的次数

using (var dbcontext= new ModelFirstDemoEntities())
{
    dbcontext.Configuration.LazyLoadingEnabled = false;
            #region 显式加载:查询部分列数据,前提关闭 懒加载
            //查询表中部分列的数据
            var items = from c in dbcontext.Customer
                        select c;
            foreach (var item in items)
            {
                //条件判断,只加载满足条件的数据,减少访问数据库的次数
                if (item.Id < 5)
                {
                    dbcontext.Entry(item).Collection(c => c.Order).Load();
                    Console.WriteLine(item.CusName);
                }

                foreach (var order in item.Order)
                {
                    Console.WriteLine("Course name : {0}", order.OrderContent);
                }
            }
            #endregion
}

按需加载:只加载自己所需要的某些列,避免加载大量的垃圾数据 

3) 注意事务的简短性:尽量把与事务无关的东西放到事务外执行,事务执行时间过长,会引起资源死锁

4) NoTracking的使用:查询出来的实体,如果不需要删除和修改,就用NoTracking查询。context.People.Where(p => p.PersonID > 100).AsNoTracking().ToList();

4、EF大数据如何批量处理?

答:拼接成Sql,一次性执行

5) IEnumerable 和 IQueryable的区别?

答:IEnumerable<T> 泛型类在调用自己的SKip 和 Take 等扩展方法之前数据就已经加载在本地内存里了,而IQueryable<T> 是将Skip ,take 这些方法表达式翻译成T-SQL语句之后再向SQL服务器发送命令,它并不是把所有数据都加载到内存里来才进行条件过滤

 

linq to sql

var q =
    from p in db.Products
    group p by p.CategoryID into g
    where g.Count() >= 10
    select new {
        g.Key,
        MinPrice = g.Min(p => p.UnitPrice), //最小值
        AveragePrice = g.Average(p => p.UnitPrice), //平均值
        TotalPrice = g.Sum(p => p.UnitPrice), //求和
        ProductCount = g.Count() ,
        NumProducts = g.Count(p => p.Discontinued)  //带条件计数
    };

  

  

 

泛型

什么是泛型?使用泛型有什么好处?你是怎么用的

 带泛型参数的类型就是泛型。

 主要是为了代码重用,扩展性,保护类型安全和提高性能。

 .NET支持的类型参数主要有以下5种:

namespace RhAutofac
{
    public class BaseManager<T, K, V, W, X>
        where T : struct //必须是值类型(如int)
        where K : class //必须是引用类型(如object,string,类)
        where V : IComparable //必须是实现了IComparable接口(如int)
        where W : K //要求W必须继承于K,这种叫裸类型约束
        where X : class,new() //X必须是引用类型,并且要有一个无参的构造函数(对于一个类型有多有约束,中间用逗号隔开)
    {
        public void say(X obj)
        {
            Console.WriteLine(obj.ToString());
        }
    }
}

泛型的性能和安全性体现在哪里?

ArrayList list = new ArrayList();
list.Add(2);
list.Add(4);
list.Add("a");
foreach (int i in list)
{
    Console.WriteLine(i);
}

我们往ArrayList集合添加元素的时候可以看到,add()的参数是ojbect类型,如果添加int类型的话会发生装箱操作,在循环迭代的时候自然是拆箱了,装箱和拆箱自然有性能损失

上述代码在编译期间是无错误的,但在运行期间就出错了,这是我们不希望看到的,所以引入泛型

 

 多线程

 

 

反射

 

service

 

并发

了解lock的作用、具体用法

 

曾有这么一道上机面试题:

在最短的时间内插入50万条数据

 

 

 

数据库

1: SQL Server分页

int iStartNum = pageSize * (pageIndex - 1) + 1;
int iEndNum = pageSize * pageIndex;
SELECT * FROM ( 
SELECT ROW_NUMBER() OVER (order by T.CreateDateTime desc) AS Row, T.*  from (" + sql + ") as T 
) TT 
WHERE TT.Row between " + iStartNum + " and " + iEndNum

2. 如何采用递归方式获取父节点(或子节点)

  with...as ( ----- ) select * from ...

3. 行转列(有这么一道面试题)

    考察case when...then

--创建表结构
create table Department(depId nvarchar(10), depName nvarchar(36))
insert into Department(depId,depName) values('01','国内业务一部')
insert into Department(depId,depName) values('02','国内业务二部')
insert into Department(depId,depName) values('03','国内业务三部')
insert into Department(depId,depName) values('04','国际业务部')
insert into Department(depId,depName) values('05','国内业务四部')

create table Performance(mon nvarchar(10), depId nvarchar(10), score nvarchar(10))
insert into Performance(mon,depId,score) values('一月份','01','10')
insert into Performance(mon,depId,score) values('一月份','02','10')
insert into Performance(mon,depId,score) values('一月份','03','5')
insert into Performance(mon,depId,score) values('二月份','02','8')
insert into Performance(mon,depId,score) values('二月份','04','9')
insert into Performance(mon,depId,score) values('三月份','03','8')
insert into Performance(mon,depId,score) values('一月份','01','3')


--静态SQL
select dep.depName,SUM(case mon when '一月份' then score  else 0 end) as 一月份,
SUM(case when mon='二月份' then score else 0 end) as 二月份,
SUM(case when mon='三月份' then score else 0 end) as 三月份,
SUM(case when mon='四月份' then score else 0 end) as 四月份,
SUM(CAST(score as decimal(18,0))) as 总业绩,
CAST(AVG(CAST(score as decimal(18,0))) as decimal(18,0)) as 业绩平均值
from Performance p left join Department dep on p.depId=dep.depId group by dep.depName


select * from Performance pivot(max(score) for mon in(一月份,二月份,三月份,四月份)) b --order by score
View Code

4. 有一张表有重复数据,请问在SQL Server中如何去掉重复行?

  delete from TestTable where ID in ( select min(ID) ID from TestTable group by A,B having Count(0)>1)

5. 存储过程的创建,如何定义变量,传参,在c#中如何调用存储过程

6. 视图

7. 游标

8. 函数

9. sql性能优化 

AutoFac

描述下你所理解的AutoFac,在实际项目中哪些地方用到过?它有什么作用?

 我们在做开发时候的业务逻辑层和持久层,其实业务层不需要关心数据是怎么来的,所以业务层应与持久层解耦合,解耦合的方法就是'依赖于抽象,而不依赖于具体'

 1.创建组件,通过组件获取对象实例。创建组件有4种方式,分别是类型创建、实例、Lamdba表达式和程序集创建

 2.同一个服务的不同实现可以由类型、名称和键区分

 3.选择不同的构造函数,添加额外的构造函数参数,自动装配,减少重复配置

 4.泛型注册

 5.解耦

 

Redis

在实际项目中哪些场景用到过,是怎么用的?

1. 为什么用redis做缓存?使用redis有哪些好处?

主要是为了缓解服务器频繁读数据库带来的内存资源消耗,redis将需要和数据库交互的信息暂存,当下次同样的http请求,就能直接读取redis里面的内容,而不用读数据库。这样减少了数据库压力又能提高服务器响应时间

(1) 速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1)

(2) 支持丰富数据类型,支持string,list,set,sorted set,hash

(3) 支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行

(4) 丰富的特性:可用于缓存,消息,按key设置过期时间,过期后将会自动删除

2. redis相比memcached有哪些优势?

(1) memcached所有的值均是简单的字符串,redis作为其替代者,支持更为丰富的数据类型

(2) redis的速度比memcached快很多

(3) redis可以持久化其数据

3、如何部署redis集群,怎么实现多台服务器共享的,说说你的思路?

要让集群正常工作至少需要3个主节点(即需要3个实例),我们可以创建6个redis节点,其中三个为主节点,三个为从节点,每个节点分配一个端口(6380,6381…),默认端口是6379,每个节点对应一个Redis.conf配置文件。

强烈建议配置master和slave主从架构,直接在配置文件修改slaveof(永久),使用redis-cli客户端设置redis服务(暂时),redis重启失效,我们修改对应的配置文件的端口号、认证密码,requirepass是认证密码,之后为了避免一个redis服务宕机,导致应用宕机的情况,我们启用sentinel(哨兵)服务,实现主从切换的功能要作主从切换,所以建议所有的密码都一致, masterauth是从机对主机验证时所需的密码。

当数据量变得庞大的时候,读写分离也还是很有必要的。

redis 的存储分为内存存储、磁盘存储和log文件三部分,配置文件中有三个参数对其进行配置。

save seconds updates:在指定时间内,达到多少次更新操作时,就将数据同步到数据文件。这个可以多个条件配合,比如默认配置文件中的设置,就设置了三个条件。

appendonly yes/no:是否在每次更新操作后进行日志记录,如果不开启,可能会在断电时导致一段时间内的数据丢失。因为redis本身同步数据文件是按上面的save条件来同步的,所以有的数据会在一段时间内只存在于内存中。

appendfsyncno/always/everysec:no表示等操作系统进行数据缓存同步到磁盘,always表示每次更新操作后手动调用fsync()将数据写到磁盘,everysec表示每秒同步一次。

 

主从复制的步骤:

1、从服务器开始链接主服务器时,会向主服务器发送一个 SYNC 命令 
2、主服务接收到命令之后,执行 BGSAVE,异步的将写命令保存到一个缓冲区里面 
3、主服务器执行完BGSAVE之后,就.rdb 文件(BOF的持久化文件)发送给从服务器,从服务器从该文件恢复数据到内存中 
4、主服务器还会以 Redis 命令协议的格式, 将写命令缓冲区中积累的所有内容都发送给从服务器,从服务器通过执行命令将数据恢复到内存中


4、redis的事务如何处理?


5、怎么保证redis与db数据的一致性?

1、查询时先查询缓存(Redis),如果查询不到,查询数据库,并将会员唯一标识(会员编号),放到redis队列中(list)

2、启动一个job从redis队列中读取会员唯一标识,并判断会员编号作为key是否存在于redis中,如果存在,计数器减一,否则直接查询会员信息,放到redis中。

2、更新时,先更新数据库,再清空对应redis信息,并将会员编号做为key的计数器加一

6、redis的多实例有什么作用?

答:redis是单一线程,同一时刻只有一个操作,所以耗时的的命令会导致并发的下降,不只是读并发,写并发也会下降。而单一线程也只能用到一个cpu核心,所以可以在同一个多核的服务器中,可以启动多个实例,组成master-master或者master-slave的形式,耗时的读命令可以完全在slave进行。

6、redis有时候会请求超时,已知都是固定的一个时间,比如200ms或者500ms,问这是为什么?

请求redis超时,如果时间较长,比如60s或者75s这样的,可能是redis的timeout配置。目前是时间较短,200ms就超时,一般来说redis没道理在能处理请求的时候报超时错误,会否是现在超过了redis设置的最大连接数maxclients,导致拒绝服务;会否是client自身的连接超时设置。
无论如何,CS模式的两端都有可能是原因

7、mySQL里有2000w数据,redis中只存20w的数据,如何保证redis中的数据都是热点数据?

相关知识:redis 内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略。redis 提供 6种数据淘汰策略:

volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰

volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰

volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰

allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰

allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰

no-enviction(驱逐):禁止驱逐数据


8. redis常见性能问题和解决方案:

(1).Master写内存快照,save命令调度rdbSave函数,会阻塞主线程的工作,当快照比较大时对性能影响是非常大的,会间断性暂停服务,所以Master最好不要写内存快照。

(1) Master最好不要做任何持久化工作,如RDB内存快照和AOF日志文件

(2) 如果数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次

(3) 为了主从复制的速度和连接的稳定性,Master和Slave最好在同一个局域网内

(4) 尽量避免在压力很大的主库上增加从库

(5) 主从复制不要用图状结构,用单向链表结构更为稳定,即:Master <- Slave1 <- Slave2 <- Slave3...

这样的结构方便解决单点故障问题,实现Slave对Master的替换。如果Master挂了,可以立刻启用Slave1做Master,其他不变。

9、SAVA和BGSAVA的区别?

 SAVE 和 BGSAVE 两个命令都会调用 rdbSave 函数,但它们调用的方式各有不同:• SAVE 直接调用 rdbSave ,阻塞 Redis 主进程,直到保存完成为止。在主进程阻塞期间,服务器不能处理客户端的任何请求。• BGSAVE 则 fork 出一个子进程,子进程负责调用 rdbSave ,并在保存完成之后向主进程发送信号,通知保存已完成。因为 rdbSave 在子进程被调用,所以 Redis 服务器在BGSAVE 执行期间仍然可以继续处理客户端的请求。

 10、[秒杀]是怎么实现的?

 redis计数器

Redis incr 可以实现原子性的递增,可应用于高并发的秒杀活动、分布式序列号生成等场景。这里我使用它来计数实现一分钟内只接受一次请求。

我们在后台接到短信发送请求后,使用Redis的incr设置一个递增KEY(KEY由固定字符串+手机号码组成),并判断该KEY的数值,如果等于1,说明是第一个请求,我们将该KEY值有效期设置为一分钟;如果该KEY的数值大于1,说明是1分钟内的多次请求,这时我们直接返回短信获取频繁,代码如下:

String redisKey = "SMS_LIMIT_" + smsPhone;
long count = redisTemplate.opsForValue().increment(redisKey, 1);
if (count == 1) {
//设置有效期一分钟
redisTemplate.expire(redisKey, 60, TimeUnit.SECONDS);
}
if (count > 1) {
resultMap.put("retCode", "-1");     resultMap.put("retMsg", "每分钟只能发送一次短信");
outPrintJson(resultMap);
return;
}
/** 发送短信 */
......
/** 记录发送日志 */
......

 

Redis的快照与AOF

快照的优势

快照的文件适合定时备份

AOF日志:追加文件

高并发的业务架构:

  • 前端:异步请求+资源静态化+CDN内容分发
  • 后端:请求队列+轮询分发+负载均衡(软件负载均衡、硬件负载均衡)+共享缓存
  • 数据层:redis缓存+数据分表+写队列
  • 存储:raid阵列+热备
  • 网络:dns轮询+DDOS攻击防护

1. 镜像站点
2. DNS负载均衡
2. Web缓存服务器
3. Web/应用服务器分布式文件系统
4. 分布式数据库(数据库主从分布、数据库分割、数据库缓存)

 内存优化:   http://www.infoq.com/cn/articles/tq-redis-memory-usage-optimization-storage/

http://blog.csdn.net/lang_man_xing/article/details/38386113

 

SSO单点登录

你是怎么解决单点登录cookie的跨域问题的?

 

环境1:a.xxx.com需要跟b.xxx.com实现跨域,这种比较简单,只需要设置cookie的域名关联域就可以了 cookie.Domain = "xxx.com",这样两个域名间的cookie就可以互相访问,实现跨域.

环境2:a.aaa.com需要跟b.bbb.com实现跨域,这种不同域名的情况下,想要实现就必须换种方式了.

 在这里我将引入第三者,s.sss.com这个站点,就是某个浏览器同时打开了这3个站点,我们访问A站点,先判断自身是否登录,如果session为空,就重定向到S站点,判断S站点上面是否有cookie,如果S站点上面也没有cookie,则由S站点重定向到A站点的登录页.

 这样我们就实现了第一步,S站做的的就是隐藏在幕后,子站先判断自己是否存在session,如果不存在,就重定向到主站S上面去验证.

第二步,验证登录信息合法性.这里我引入token(令牌),网上有很多资料,描述token的传递,工作方式是这样,A登录成功,保存自身的session,重定向到S,S在自己站点保存一个session跟cookie,session保存token对象{tokenID,userName,startTime,endTime},cookie保存tokenID,tokenID是一个Guid,把token对象缓存在集合里面,另起一个线程,根据endTime(过期时间)来定期清理集合列表,重定向到A的时候再将tokenID传递过去,拿到tokenID后,进入验证环节,S站有提供一个接口,根据tokenID获取token对象,如果获取到对象,且没有失效,则tokenID合法,跳入index页面.情况2,A登录,直接打开B,这时候B自身没有session,会主动请求主站,主站会返回cookieID(S站存在客户端的cookie),这个时候再走验证环节,如果通过,则B根据token对象创建自身的session,再跳入index.

要理ajax解跨域重定向,先要了解浏览器对重定向的处理。正常我们请求一个地址,如果server返回302,那么浏览器会再发起一次重定向后的http请求;用jquery ajax发起一次异步请求,server返回302,如果重定后url的域名跟ajax请求的域名是同一个域名的话,浏览器会再发起一次重定向后的http请求,请求成功会调用ajax的success函数,如果重定向后url的域名跟ajax请求的域名不是同一个域名,也就是跨域重定向(跨域redirect),这个时候浏览器看到返回的response的Location跨域了就不会再发起请求,请求被拦截了,ajax请求失败会调用error方法

那么如果我们非要做跨域重定向呢?这也是可以实现的,普通的ajax请求不行,我们需要通过jsonp的方式,而且需要设置crossDomain:true,可以参考https://api.jquery.com/jQuery.ajax/  关于jquery.ajax方法的crossDomain 参数的说明

<script src="jquery.js"></script>  
<script type="text/javascript">  
var res=$.ajax({  
  type:"get",  
  dataType:"jsonp",/*-----------------------*/  
  url: "http://api.luojisiwei-inc.com/test/test.php?callback=?",  
  crossDomain:true,/*-----------------------*/  
  success: function(data){  
                alert("success:"+data.name);  
          
        },  
  beforeSend:function(){  
        },  
  complete:function(data,status){  
        }  
});  
  
</script>  

  

 lucene全文检索

1、lucene的工作方式
lucene提供的服务实际包含两部分:一入一出。所谓入是写入,即将你提供的源(本质是字符串)写入索引或者将其从索引中删除;所谓出是读出,即向用户提供全文搜索服务,让用户可以通过关键词定位源。

2.1写入流程
源字符串首先经过analyzer处理,包括:分词,分成一个个单词;去除stopword(可选)。
将源中需要的信息加入document.各个Field中,并把需要索引的Field索引起来,把需要存储的Field存储起来。
将索引写入存储器,存储器可以是内存或磁盘。

2.2读出流程
用户提供搜索关键词,经过analyzer处理。
对处理后的关键词搜索索引找出对应的document.
用户根据需要从找到的document.提取需要的Field。

 

算法题

1、一列数的规则如下: 1、1、2、3、5、8、13、21、34...... 求第30位数是多少,用递归算法实现。

2、请编程实现一个冒泡排序算法?

 

3、向一个数组中插入一个1~100的随机数

static void Main(string[] args) 
{ 
      List<int> list = new List<int>(); 
      Random ran = new Random(); 
        
      while(true) 
      { 
        if (list.Count >= 100) 
        { 
          break; 
        } 
        int s = ran.Next(1, 101); 
        if (!list.Contains(s)) 
        { 
          list.Add(s); 
        } 
      } 
  
      list.Sort(); 
  
      foreach (int i in list) 
      { 
        Console.Write(i + " "); 
      } 
      Console.ReadKey(); 
}

  

 

1、构造函数后边的:base和:this的区别:base的作用是调用父类的构造函数,this是调用本身

2、

常见的笔试题

1、C#中的委托是什么?事件是不是一种委托?

答:委托可以把一个方法作为参数代入另一个方法。委托可以理解为指向一个函数的引用。
  是,是一种特殊的委托

2、简述private、 protected、 public、internal修饰符的访问权限。
答:private : 私有成员, 在类的内部才可以访问。
  protected: 保护成员,该类内部和继承类中可以访问。
  public: 公共成员,完全公开,没有访问限制。
  internal:在同一命名空间内可以访问。

3、override与重载的区别
答:重载是方法的名称相同,参数或参数类型不同
  Override是进行基类中函数的重写

4、虚方法的关键词是什么?什么是接口、抽象类、抽象方法?重写中new有什么作用?

答:new: 对应的基类方法可用可不用virtual关键字。这种方法叫隐藏基类方法。

4、如果在一个B/S结构的系统中需要传递变量值,但是又不能使用Session、Cookie、Application,您有几种方法进行处理?

答:this.Server.Transfer

5、描述一下C#中索引器的实现过程,是否只能根据数字进行索引?

答:不是。可以用任意类型。

6、什么是装箱和拆箱?

答:引用类型的对象将在堆上分配内存,而值类型的对象则会在堆栈上分配内存

装箱是值类型转换成引用类型,拆箱是则相反

值类型有结构体(int类型,bool型,用户定义的结构体),枚举,可空类型

引用类型有object、string、数组、类、接口、委托

 

 

10. 求以下表达式的值,写出您想到的一种或几种实现方法:1-2+3-4+……+m
答:
int Num = this.TextBox1.Text.ToString() ;
int Sum = 0 ;
for (int i = 0 ; i < Num + 1 ; i++)
{
if((i%2) == 1)
{
Sum += i ;
}
else
{
Sum = Sum - I ;
}
}
System.Console.WriteLine(Sum.ToString());
System.Console.ReadLine() ;

 

 

 

基础题:
1.简述string[]、ArrayList、List与的区别。

http://www.cnblogs.com/ICanSoft/p/4623117.html

数组在内存中是连续存储的,所以它的索引速度非常快,而且赋值和修改元素也非常简单,效率快; 插入和删除很麻烦,效率低,而且初始化必须指明数组长度

ArrayList初始化可以不指定长度,动态插入或删除项,存放的数据类型可以是不同类型的数据; ArrayList不是类型安全的,其插入的数据当做Object类型处理,因此在处理数据是可能会报类型不匹配错误,由于存在装箱和拆箱操作,会带来很大的性能损耗,所以存取效率低

List声明时必须指定数据集内元素的数据类型,且数据元素类型必须相同,可以动态插入或删除数据元素,数据操作是类型安全的且不存在装箱和拆箱操作,因此效率较高。
2.简述装箱和拆箱操作中的性能损耗是如何产生的。

 

装箱和拆箱是要尽量避免的操作。同时,尽可能少用Array,它的ADD操作会将值类型变量转为引用类型,而泛型List则不会,它是一个增强版的Array,它可以直接添加值类型到List中。

 

int i = 4;  //i是值类型,分配在栈上

//[装箱]这个值类型被复制并分配到托管堆,并把它转成引用类型ojb
object obj = i;  //obj是引用类型,分配在托管堆,变量包含实例的指针,通过此指针引用其实例

//[拆箱]将托管堆中的引用类型实例复制到栈中,转为值类型a
int a = (int)obj;

 

3.简述对ASP.NET中的事件机制的理解。
4.在一个ASP.NET的三层结构系统中,以登录操作为例,简述在各层中如何组织代码。
5.简述相比DATASET,实体类在WEB项目中的优点与缺点。
6.简述GC是如何工作的。
7.简述3个熟悉的设计模式。
8.简述UDP协议特点,以及如何提高UDP传输可靠性。
9.简述.NET2.0,.NET3.0,.NET3.5各版本中推出的新特性。

 

 

类似算法题:

一列数的规则如下: 1、1、2、3、5、8、13、21、34......  求第30位数是多少, 用递归算法实现。

public static int Foo(int i)
{
if (i <= 0)
{
return 0;
}
else if (i > 0 && i <= 2)
{
return 1;
}
else
{
int x = Foo(i - 1);
int y = Foo( i - 2);
int a = x + y;
return a;
}

}

  

请编程实现一个冒泡排序算法?

public static int Foo(int i)
{
if (i <= 0)
{
return 0;
}
else if (i > 0 && i <= 2)
{
return 1;
}
else
{
int x = Foo(i - 1);
int y = Foo( i - 2);
int a = x + y;
return a;
}

}

  

求以下表达式的值,写出您想到的一种或几种实现方法: 1-2+3-4+……+m

public static int Foo(int i)
{
if (i <= 0)
{
return 0;
}
else if (i > 0 && i <= 2)
{
return 1;
}
else
{
int x = Foo(i - 1);
int y = Foo( i - 2);
int a = x + y;
return a;
}

}

  

 

 

网站性能需要优化,你会从哪几个方面入手

http://blog.csdn.net/shyleoking/article/details/7277898

100道c#题

http://blog.csdn.net/u013519551/article/details/51220841

 

posted @ 2020-06-17 10:59  九幽旋律  阅读(282)  评论(0编辑  收藏  举报