C#.NET⾼级⾯试题
1. DateTime.Parse(myString); 这段代码有什么问题?
A:区域信息即CultureInfo没有指定。如果不指定的话,它将采⽤默认的机器级的设置(见:控制⾯板->区域和语⾔选项)并使⽤这个设置来决定这个字符串即myString怎样被解释。所以如果你传⼊“5/2/2005”且你的区域设置为En-US,则它会被解释为May 2nd 2005,但是如果你的区域设置为Hindi-India,则它会被解释为5th Feb 2005!
参考下⾯的代码⽰例:
string sDate = "5/2/2005"; //本意是2005年5⽉2号
DateTime[] dt = new DateTime[3];
CultureInfo[] cf = new CultureInfo[3];
cf[0] = new CultureInfo("en-US", true); //指定为en-US,字符串将被解释为“MM/DD/YYYY”
dt[0] = DateTime.Parse(sDate, cf[0], DateTimeStyles.AllowWhiteSpaces);
dt[0] = dt[0].AddMonths(1); //另⽇期变为2005年6⽉2⽇
Console.WriteLine(dt[0].ToString(cf[0]));
cf[1] = new CultureInfo("hi-IN", true); //这是印度格式,字符串被解释为“DD/MM/YYYY”
dt[1] = DateTime.Parse(sDate, cf[1], DateTimeStyles.AllowWhiteSpaces);
dt[1] = dt[1].AddMonths(1); //让它变成2005年3⽉5⽇
Console.WriteLine(dt[1].ToString(cf[1]));
好了,这解决所有问题了吗?没有!
如果时间放在⼀个⽂本框中 – 有些⼈输⼊了“2005/02/05” – 我不知道我应该怎样解释这个输⼊呢! “DateTime.ParseExact” 要求你必须告诉计算机怎样处理输⼊的⽇期字符串它才可以处理。
//抛出FormatException
cf[2] = new CultureInfo("hi-IN", true);
dt[2] = DateTime.ParseExact(sDate, new string[] { "d" }, cf[2], DateTimeStyles.AllowWhiteSpaces); //抛出Format Exception
dt[2] = dt[2].AddMonths(1);
Console.WriteLine(dt[2].ToString(cf[2]));
第⼆个参数指定了输⼊字符串的格式 – “d”意思是短⽇期 – MM/dd/yyyy – 查看⽂档中的DateTimeFormatInfo类中全部的格式。
上⾯的代码会抛出⼀个FormatException,因为你没有遵守规则。
好了,现在我们⼏乎完成了,如果想让⼀个字符串表达式被接受怎么办呢?
使⽤⼀个⾃定义表达式。如下:
sDate = "2005/05/02";
dt[2] = DateTime.ParseExact(sDate, new string[] { "%yyyy/MM/dd" }, CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces);
dt[2] = dt[2].AddMonths(1);
Console.WriteLine(dt[2].ToString(cf[2]));
这样就可以接受了
2. PDB是什么东西?在调试时它应该放在哪⾥?
A:以下是摘⾃MSDN⼀段说明A program database file (extension .pdb) is a binary file that contains type and symbolic debugging information gathered over the course of compiling and linking the project. A PDB file is created when you compile a C/C++ program with /ZI or /Zi or a Visual Basic, Visual C#, or JScript program with the /debug option. Object files contain references into the .pdb file for debugging information. For more information on pdb files, see PDB Files (C++). A DIA application can use the following general steps to obtain details about the various symbols, objects, and data elements within an executable image.
翻译后(部分):程序数据库⽂件(扩展名:pdb)是⼀个⼆进制⽂件包含了在编译和链接项⽬过程中收集的类型与符号调试信息。PDB⽂
件在你使⽤/ZI或/Zi参数编译⼀个C/C++程序或使⽤/debug参数编译⼀个Visual Basic, Visual C#或Jscri
pt程序时⽣成。⽬标⽂件含有到.pdb ⽂件的引⽤以查调试信息。
下⾯是查询此⽂件内容的⽅法:
u Acquire a data source by creating an IDiaDataSource interface.
u Call IDiaDataSource::loadDataFromPdb or IDiaDataSource::loadDataForExe to load the debugging information.
u Call IDiaDataSource::openSession to open an IDiaSession to gain access to the debugging information.
u Use the methods in IDiaSession to query for the symbols in the data source.
u Use the IDiaEnum* interfaces to enumerate and scan through the symbols or other elements of debug information.
调试时,PDB⽂件应该与待调试⽂件放在同⼀⽬录下。
3. 什么是圈复杂度(Cyclomatic Complexity)?为什么它很重要?
A:圈复杂度⼀种代码复杂度的衡量标准,中⽂名称叫做圈复杂度。在软件测试的概念⾥,圈复杂度“⽤来衡量⼀个模块判定结构的复杂程度,数量上表现为独⽴现⾏路径条数,即合理的预防错误所需测试的最少路径条数,圈复杂度⼤说明程序代码可能质量低且难于测试和维护,根据经验,程序的可能错误和⾼的圈复杂度有着很⼤关系”。
4. 写⼀个标准的lock(),在访问变量的前后创建临界区,要有“双重检查”。
A: 这即是Jeffrey Richter在其经典著作CLR Via C#中提到的双检锁(double-check locking)技巧。如下是原书代码:
public sealed class Singleton
{
private static Object s_lock = new Object();
private static Singleton s_value;
//私有构造器组织这个类之外的任何代码创建实例
private Singleton() { }
// 下述共有,静态属性返回单实例对象
public static Singleton Value
{
get
{
// 检查是否已被创建
if (s_value == null)
writeline方法的作用{
// 如果没有,则创建
lock (s_lock)
{
/
/ 检查有没有另⼀个进程创建了它
if (s_value == null)
{
// 现在可以创建对象了
s_value = new Singleton();
}
}
}
return s_value;
}
}
}
5. 什么叫FullTrust?放⼊CAC的assembly是否是FullTrust的?
FullTrust权限基本上允许跳过所有的CAS验证,持有该权限的程序集能够访问所有的标准权限。GAC中的程序集是具有FullTrust权限的。详细信息参见此。
6. 代码加上需要安全权限的特性有什么好处?
A: 有可能会通过具有元权限程序集或⼯具访问这些attribute及其参数。有可能在程序集级别使⽤其中的⼀些attribute。可以通过反射访问设置信息。最关键⼀点使程序集开始执⾏时⽽不是在执⾏期间声明需要权限,这样可以确保⽤户不会在程序开始⼯作后遇到障碍。
7. gacutil /l | find /i “Corillian”这句命令的作⽤是什么?
A: gacutil全称.NET Global Assembly Cache Utility。参数/l [ <assembly_name> ]的作⽤:列出通过 <assembly_name> 筛选出的全局程序集缓存。find命令作⽤:在⽂件中搜索字符串,其参数/i作⽤是搜索字符串时忽略⼤⼩写。所以这条命令的意思就是在所有的全局程序缓存中搜索名称包含字符串”Corillian”的程序集。
8. sn -t foo.dll这句命令的作⽤?
A: sn是.NET Framework 强名称实⽤⼯具,其中参数-T[p] <assembly>作⽤是显⽰ <assembly> 的公钥的标记(如果使⽤了-Tp,则还同时显⽰公钥本⾝)。此命令显⽰了foo.dll的公钥。如果foo.dll⾮强名程序集产⽣如下提⽰:未能将密钥转换为标记 -- 程序集“(null)”的公钥⽆效。
9. DCOM需要防⽕墙打开哪些端⼝?端⼝135是⼲嘛⽤的?
A: DCOM动态的选择1024~65535之间的⽹络端⼝。此外,DCOM要⽤135端⼝实现⼀些重要的功能。DCOM是使⽤RPC进⾏通讯的。利⽤RPC功能进⾏通信时,就会向对⽅电脑的135端⼝询问可以使⽤那个端⼝进⾏通讯。这样,对⽅的电脑就会告知可以使⽤的端⼝号,实际的通讯将使⽤这个端⼝来进⾏。
135端⼝起的是动态的决定实际的RPC通讯使⽤的端⼝映射功能,主要⽤于使⽤RPC(Remote Procedure Call,远程过程调⽤)协议并提供DCOM(分布式组件对象模型)服务。
10. 对⽐OOP和SOA,它们的⽬的分别是什么?
⾯向对象主要⽤于对具体的事物进⾏抽象建模,⽽SOA的主要⽬的是定义部署和管理服务的⽅式,采⽤SOA的架构可以提⾼可重⽤性,降低总成本,提⾼快速修改与演化IT系统的能⼒。
11. XmlSerializer是如何⼯作的?使⽤这个类的进程需要什么ACL权限?
XmlSerializer提供了⽅法,使你能够将⾃⼰的对象序列化和反序列化为XML,同时在这个过程中提供⼀定的控制。这个过程由⼀些attribute 来控制。以下是代码⽰例:
序列化:
Theater theater = … ;
XmlSerializer xs = new XmlSerializer( typeof ( Theater ) );
FileStream fs = new FileStream( args[0], FileMode.Create );
xs.Serialize( fs, theater );
反序列化:
XmlSerializer xs = new XmlSerializer( typeof ( Theater ) );
FileStream fs = new FileStream( args[0], FileMode.Open );
Theater theater = (Theater)xs.Deserialize( fs );
控制这个过程:
[XmlRoot( "theater" )] -- 序列化xml的根节点
[XmlElement( "name" )] -- 序列化为xml的元素及元素名称
[XmlAttribute( "minutes" )] -- 序列化为xml中的特性及其名称
[XmlElement( "showing", DataType="time" )] -- 序列化为xml的元素及其类型
ACL权限上需要执⾏程序集的⽤户拥有对C:\WINDOWS\Temp\的访问权限
12. 为什么不提倡catch(Exception)?
Exception类包含许多⼦类,程序执⾏的时候要将每⼀个类都搜索⼀遍以到符合的异常类,这样是蛮消耗资源的,影响程序运⾏效率。另外,只捕捉特定环境,特定条件下的异常,并进⾏处理。不应该捕捉所有异常,因为有些异常是我们所⽆法预料到的,⽐如,内存溢出或其他错误,这种情况下,不应该让系统以⼀种未知状态继续运⾏。
13. Debug.Write和Trace.Write有什么不同?何时应该使⽤哪⼀个?
Debug类提供⼀组帮助调试代码的⽅法和属性。Trace类提供⼀组帮助跟踪代码执⾏的⽅法和属性,通俗的说就是为在不打断程序的调试或跟踪下,⽤来记录程序执⾏的过程。
Debug只在debug状态下会输出,Trace在Release下也会输出,在Release下Debug的内容会消失。
14. Debug Build和Release Build的区别,是否会有明显的速度变化?请说明理由。
⾸先以⼀个表格说明问题:
项⽬Debug Release
条件编译常数Debug;Trace Trace
优化代码False True
输出路径bin\Debug bin\Release
⽣成调试信息True False
Debug模式下⽣成的程序集为调试版本,未经优化;在bin\debug\⽬录中有两个⽂件,除了要⽣成的.exe或.dll⽂件外,还有个.pdb⽂件,这个.pdb⽂件中就记录了代码中的断点等调试信息;Release模式下不包含调试信息,并对代码进⾏了优化,\bin\release\⽬录下只有⼀个.exe 或.dll⽂件。在项⽬⽂件夹下除了bin外,还有个obj⽬录。编译是分模块编译的,每个模块的编译结果就保存在了obj⽬录
下。最后会合并为⼀个exe或者dll⽂件保存到bin之中。因为每次编译都是增量编译,也就是只重新编译改变了的模块,所以这个obj的⽬录的作⽤就是保存这些⼩块的编译结果,加快编译速度。
15. JIT是以assembly为单位发⽣还是以⽅法为单位发⽣?这对于⼯作区有何影响?
JIT编译是以⽅法为单位完成的,当⽤到相应的⽅法才把其编译执⾏,并将编译结果暂存当下⼀次⽤到时就不⽤再编译。可以⼀定程度上提⾼效率。
16. 对⽐抽象基类和接⼝的使⽤
如果要让⾃定义类包含基类的实现,应该选⽤抽象基类,接⼝多做契约使⽤。.NET中类只允许单继承,但接⼝允许多继承。
17. a.Equals(b)和a==b相同吗?
对于值类型的⽐较两者效果相同(值类型ValueType重写了Equals⽅法)。对于除string以外的引⽤类型==⽐较对象是否为同⼀引⽤,对于string,==⽐较字符串的内容。⽽Equals⽅法对所有引⽤对象都是⽐较其是否为同⼀对象的引⽤。
很多⾃定义类都会重写Equals所以不要只注意默认实现。
18. 在对象⽐较中,对象⼀致和对象相等分别是指什么?
对象⼀致指的是两个对象是否指向托管堆中同⼀个⽬标,其⽐较对象的类型与值两个⽅⾯。对象相等指的是两个对象中的数据成员是否相等。前者是⼀种浅⽐较,后者是⼀种深⽐较。
19. 在.NET中如何实现深拷贝(deep copy)?
实现深拷贝的程序结构基本如下:
⽰例代码:
//实现ICloneable接⼝
public class Copy:ICloneable
{
//实现ICloneable接⼝的Clone()⽅法
public override object Clone()
{
//在此实现深拷贝
}
}
实现深拷贝的代码中,新建⼀个对象,然后将对象的成员逐个赋值给新对象的成员。最后将新对象返回。
20. 请解释⼀下ICloneable
当⽤户需要实现除MemberwiseClone之外的拷贝⽅法时(如深拷贝),⽤户可以实现ICloneable接⼝,并重写Clone()⽅法。在Clone()⽅法中编写⾃⼰的实现。
21. 什么叫装箱。
将值类型对象放到托管堆中需要⼀个装箱操作。需要装箱的情况有很多,⽐如将值类型数据存⼊⼀个数组(Array类)时,值类型会被装箱然后存⼊托管堆。
22. string是值类型还是引⽤类型?
string这个引⽤类型是⾮常特殊⼀个引⽤类型。
它有两点特殊的地⽅。第⼀点对象分配的特殊。例如,有如下语句:
string str1 = "abcd";
string str2 = "abcd";
那么在分配string类型的时候,先查看当前string类型列表是否有相同的,如果有的话,直接返回其的引⽤,否则重新分配。
第⼆点对象引⽤操作的特殊,即不同于真正意义上的引⽤操作。例如如下语句:
string str1 = "abcd";
string str2 = str1;
str2 = "efgh";// str1 is still "abcd" here
当对于⼀个新的string类型是原有对象引⽤的时候,这点和⼀般的引⽤类型⼀样,但是当新的对象发⽣变化的时候,要重新分配⼀个新的地⽅,然后修改对象指向。
因此对于string操作的时候,尤其发⽣变化的时候,会显得⽐较慢,因为其牵扯到内存地址的变化。(所以对于数据量⽐较⼤的字符操作时候,使⽤StringBuilder来说效率会提升很⾼。)
23. XmlSerializer使⽤的针对属性的模式有什么好处?解决了什么问题?
这⾥的属性指attribute。可以将不需要序列化的数据标记为[XmlIgnore],只序列化有⽤的数据,⽽不是序列化整个对象。可以省去没有必要序列化的数据序列化⼯作,提升序列化时的性能。使⽤attribute还可以指导序列化的过程,以⾃定义⽣成xml⽂档的格式。(11题对XmlSerializer有介绍)
24. 为什么不应该在.NET中使⽤out参数?它究竟好不好?
当想要⼀个函数产⽣多个输出时,可以使⽤out参数返回函数的输出值。这应该是out参数最⼤的作⽤。out参数的缺陷在于,它允许⼀个未初始化变量就在函数中作为out参数使⽤。这样并不能保证在访问⼀个作为out参数的变量时,它已经被初始化过,容易产⽣错误的结果。(个⼈观点)
25. 特性能够放到某个⽅法的参数上?如果可以,这有什么⽤?
可以,作⽤可以对参数有进⼀步限定,⽐如输⼊参数为int类型,可以通过允许AttributeTargets=ParameterInfo的Attribute⾃定义实现来限定输⼊参数的⼤⼩,⽐如当输⼊参数⼩于100的时候便抱错。
对⽅法的参数设置Attribute的例⼦:
[AttributeUsage(AttributeTargets.Parameter)]
public class ParameterAtt : Attribute
{
public int Min = 100;
}
public class AttributeTest
{
public void TestMethod([ParameterAtt(Min = 100)] int par1)
{
ParameterInfo para =
MethodInfo.GetCurrentMethod().GetParameters()[0];
ParameterAtt att = ParameterAtt.GetCustomAttribute
(para, typeof(ParameterAtt)) as ParameterAtt;
if (att.Min > par1)
{
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论