作为一个.NET程序员,应该知道的不仅仅是拖拽一个控件到设计时窗口中。就像一个赛车手,一定要了解他的爱车 – 能做什么不能做什么。
本文参考Scott Hanselman给出的.NET问题列表,整理如下。包括WinForms,ASP.NET,XML以及C#和.NET基础相关的问题,有兴趣的自我检测一下吧~
参考答案另附在文章末尾,由于水平有限,难免有谬误,欢迎指正。
这里问的是强名称概念。Assembly.Load("foo.dll")加载程序集的方法是否正确?
public class c{ public c(string a) : this() {;}; public c() {;} } 这个构造函数有用吗?
· 什么叫作ViewState?是什么编码?加密了吗?到底是谁在使用ViewState?
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
一个程序至少有一个进程,一个进程至少有一个线程。线程的划分尺度小于进程,使得多线程程序的并发性高。
这个解释很形象:链接
Windows服务可以在计算机启动时自动启动,可以暂停和重新启动而且不显示任何用户界面。
EXE 可执行程序通常有一个用户界面,Console或 GUI,通常由用户来启动或停止。
以32位操作系统为例,最大寻址是4G(含虚拟内存),是通过2的32次方计算的; 当物理内存小于4G时,进程访问的内存量随着虚拟内存的增加而增加,直到4G; 4GB内存实际上包含了程序的所有部分--包括可执行代码,代码加载的所有dll,以及程序运行时使用的所有变量的内容。这个4GB内存称为虚拟地址空间,或虚拟内存。
对设计有明显影响的有2点:
在.NET中区别最明显的是int的使用,在32位下和64位下存储的数据不一样(int 4个字节32位, 8个字节64位);另外一个是编译的程序为X86则可在32、64位下同时运行。
DLL中虽然包含了可执行代码却不能单独执行,而应由Windows应用程序直接或间接调用。EXE就不用说了吧~
强类型是指尽量早的检查变量的类型, 通常在编译的时候就检查.
弱类型是指尽量推后对变量类型的检查, 通常在运行时检查。
到底哪个好? 其实各有各的好, 像ruby, javascript, 都属于week-typing, 好处是写代码的时候比较快. C#属于strong-typing, 好处是如果变量类型不对的话, 编译不会通过, Visual Studio 还会有提示. 至于写代码的速度上讲, 自从C# 3.0以来, 使用var来定义变量, 简单了很多。
PID全称是 Process Identifier, 就是进程的一个号码, 通常当系统哪个程序不听使唤的时候, 可以用它来把这个程序关闭. 而且Debug的时候, 也有用。
可能只有一个。
GAC 是指 Global Assembly Cache, 用处是放在这里的程序集可以被多个程序共同调用, .NET 中的大部分程序集都在这里. 解决的问题是节省硬盘空间以及防止Dll Hell。
面向接口:定义要实现某类功能应该遵循的统一规范,而具体实现过程由实现该接口的类型决定。
面向对象:强调对具有相同行为和属性事物的封装,更注重封装的完整性和功能的完整性。
面向方面:主要提供与业务逻辑无关的操作。比如系统中有多个地方都用到文件上传功能,可以使用面向方面的思想在所有上传文件之前对文件的大小、格式等信息进行过滤操作,而不是在每处上传代码里面完成对这些信息的过滤。
接口(Interface): 不能实列化,自己没有状态,方法也没有具体的实现,被继承时,继承类需要实现接口的所有方法。接口就像租房时网上下载的一个租房合同模板。
类 (Class): 可以被实例化,有状态,被继承时,继承类也不需要重新实现被继承类中的方法。但是如果被继承类的方法中有abstract修饰的,继承类则需要实现这个方法。类像是已经被填上内容的租房合同的模板。
代码在运行过程中动态获取程序集的信息,对象的信息,或者直接调用对象的方法或属性。 e.g. var i = 100; i.GetType(); 输出System.Int32。
XML Web service: 是开放标准,使用Http/SOAP协议交互。
.NET Remoting: 是微软自己的技术,只能在.NET里面使用。
early-binding: 是指编译的时候绑定,late-binding是指运行时绑定。
动态引用。
Assembly.LoadFile只载入相应的dll文件,其他文件并不会被载入。
Assembly.LoadFrom会载入dll文件及其引用的其他dll
这里问的是强名称概念。
它不是一个文件名,相比文件名,Assembly Qualified Name更能确定一个程序集,它包含文件名,但同时包含版本,公钥,和区域。因为同样一个名称的文件可能有不同的版本和区域,此时单独靠文件名称,可能会造成不能确定程序集的正确性。
不对,正确方式为:Assembly.Load("foo, Version=1.0.2004.0, Culture=neutral, PublicKeyToken=8744b20f8da049e3")
通过签发具有强签名的程序集合,可以确保名称的全局唯一性!因为强名称是依赖于唯一的密钥对来确保名称的唯一性,其他人不会生成与你相同的程序集名称(不同的私钥产生的名称不同)。强名称保护程序集的版本沿袭,因为强名称的唯一性能够确保没有其他人能够生成你的程序集的后续版本。强名称提供可靠的完整性检查,通过.NET Framework安全检查后,可以确保程序集内容在生成后未被更改过!
DateTime 不能为null。因为其为Struct,属于值类型,值类型不能为null,只有引用类型才能被赋值null。
JIT(Just In Time),这是我们通过.NET编译器生成的应用程序最终面向机器的编译器
本机映像生成器 (Ngen) 是一种提高托管应用程序性能的工具。 Ngen.exe 创建本机映像(包含经编译的特定于处理器的机器代码的文件),并将它们安装到本地计算机上的本机映像缓存中。运行时可从缓存中使用本机映像,而不必使用实时 (JIT) 编译器编译原始程序集。
由于 JIT 编译器会在调用程序集中定义的单个方法时将该程序集的 MSIL 转换为本机代码,因而必定会对运行时的性能造成影响。在大多数情况下,这种性能影响是可以接受的。更为重要的是,由 JIT 编译器生成的代码会绑定到触发编译的进程上。它无法在多个进程之间进行共享。为了能在多个应用程序调用或共享一组程序集的多个进程之间共享生成的代码,公共语言运行库支持一种提前编译模式。此提前编译模式使用本机映像生成器 (Ngen.exe) 将 MSIL 程序集转换为本机代码,其作用与 JIT 编译器极为相似。但是,Ngen.exe 的操作与 JIT 编译器的操作有三点不同:
· 它在应用程序运行之前而不是运行过程中执行从 MSIL 到本机代码的转换。
· 它一次编译一个完整的程序集,而不是一次编译一个方法。
· 它将本机映像缓存中生成的代码以文件的形式持久保存在磁盘上。
.NET的垃圾回收分为3代,可通过GC.Collect强制处理。
一个对象实例没有被任何地方引用时就称为垃圾,当内存不够是GC就会将该对象实例占用的空间清理出来
Finalize只释放非托管资源;
Dispose释放托管和非托管资源
Finalize和Dispose共享相同的资源释放策略,因此他们之间也是没有冲突的。
有用,限定资源作用域并自动释放。
IDisposable是一个接口,有一个方法Dispose(),可以在对象出作用域的时候调用,如在Using出界后调用这个接口。
列出所有使用符合引号内pattern的dll的进程.
In-proc 发生在一个进程之内, Out-of-proc 发生在不同进程之间。
Xp : aspnet_Wp.exe
Windows 2000 : inetinfo.exe
Windows 2003 : w3wp.exe
一般使用DateTime.TryParse解析。
PDBs是源码编译文件-全称Program Database,这个文件主要会存储对应模块(dll或者exe)内部的所有符号,以及符号对应的地址、文件名和行号。调试的时候应用程序和源文件之间的一个桥梁。
一种代码复杂度的衡量标准。
可以用来衡量一个模块判定结构的复杂程度,数量上表现为独立现行路径条数,也可理解为覆盖所有的可能情况最少使用的测试用例数。圈复杂度大说明程序代码的判断逻辑复杂,可能质量低且难于测试和维护。程序的潜在风险和高的圈复杂度有着很大关系。
lock 关键字可确保当一个线程位于代码的临界区时,另一个线程不会进入该临界区。 如果其他线程试图进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。
public class MySingleton { private static object myLock = new object(); private static volatile MySingleton mySingleton = null; private MySingleton() { } public static MySingleton GetInstance() { if (mySingleton == null) { //第一次检查 lock (myLock) { if (mySingleton == null) { // 第二次检查 mySingleton = new MySingleton(); } } } return mySingleton; } }
FullTrust即为完全信任,也称为盲目信任.
GAC:有FullTrust权限
更加灵活的设置对代码的访问权限,实现代码级保护,防止被移动代码恶意利用
全局程序集缓存中如果有Corillian就更新该程序集,没有就安装。
显示程序集的公钥标记。
因DCOM的端口号是随机分配的,默认情况下,会分配1024以上的端口号,所以默认情况下,DCOM不能穿越防火墙。
135是远程过程调用(RPC)的默认端口
OOP是一种编程模型,将复杂的逻辑分解出小的模块,特性是继承,封装和多态。而SOA是一个技术框架。 SOA的思想是将业务逻辑封装成服务或者中间件提供给应用程序来调用,当然其组件化思想是继承和发扬了OOP的优点。
XmlSerializer是将对象的属性和字段进行序列化和反序列化的,序列化成为xml数据,反序列化再将xml转换成对象。应该至少需要ACL权限中的读权限。
因为try-catch有性能损失,在性能要求高的场景下,频繁使用效果很差。同时,catch(Exception)后,可能会破坏程序的正常执行逻辑,导致阅读、调试代码难度增大。
Catch的时候应该捕捉具体的Exception类型,而不是通用的Exception
Debug只在debug状态下会输出,Trace在release下也会输出,在release下Debug的内容会消失。Debug会产生pdb文件,release不会。
Debug和Release编译产出物不一样,Release下无调试信息,如Assert无法使用。对程序运行速度而言,无明显区别。建议在开发环境下用Debug编译,发布环境下用Release,为了使用Assert断言。
方法,因对于一次运行,很可能只用到一个程序集中极少数类型和对象,而大部分可能并不会被使用。
接口(Interface)是用来定义行为规范的,不会有具体实现,而抽象类除定义行为规范外,可以有部分实现,但一个类能实现多个接口,但只能继承一个基类。接口是是一种契约,定义了继承它的类必须声明接口中的方法。
区别:
接口只有方法、属性、事件和索引符;类除了这四种成员之外还可以别的成员(如字段)。接口没有构造函数,类有构造函数。
接口不能进行运算符的重载,类可以进行运算符重载。
接口的成员没有任何修饰符,其成员总是公共的,而类的成员则可以有修饰符。派生于接口的类必须实现接口中所有成员的执行方式,而从类派生的则不然。
equals:比较两个变量的内容是否相等
==:操作比较的是两个变量的值是否相等,对于引用型变量表示的是两个变量在堆中存储的地址是否相同,即栈中的内容是否相同。
对象一致指的是引用相同。对象相等指的是内容相等。
深复制将会在新对象中创建引用类型字段引用的所有对象,改变新对象中引用的任何对象,不会影响到原来的对象中对应字段的内容。
ICloneable 接口可以提供创建现有对象中复制的自定义实现。
拆箱就是引用类型转换为值类型,通常伴随着从堆中复制对象实例的操作
装箱就是值类型数据转换为Object类型的引用对象
引用类型
把不参与序列化的对象标注出来,只序列化有用的数据,而不是序列化整个对象。去除没必要的数据冗余,和提升序列化时的性能。
之所以说out参数不好,是因为通过out参数传值,间接了破坏了封装性和函数的可读性。但笔者认为有的时候还是很实用很方便的。
可以。至少比较省事。
/// <summary>The EnableWindow Function.</summary> [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool EnableWindow(System.IntPtr hWnd, [MarshalAs(UnmanagedType.Bool)]bool enable);
override new在基类没有virtual关键字的情况下必须使用。副作用是破坏了继承关系。
virtual:virtual 关键字用于修饰方法、属性、索引器或事件声明,并使它们可以在派生类中被重写。例如,此方法可被任何继承它的类重写。
sealed:当对一个类应用 sealed 修饰符时,此修饰符会阻止其他类从该类继承。
override:要扩展或修改继承的方法、属性、索引器或事件的抽象实现或虚实现,必须使用 override 修饰符。
abstract:abstract 修饰符可以和类、方法、属性、索引器及事件一起使用。在类声明中使用 abstract 修饰符以指示某个类只能是其他类的基类。标记为抽象或包含在抽象类中的成员必须通过从抽象类派生的类来实现。
Foo.Bar: 程序集名称
Version=2.0.205.0: 程序集版本
Culture=neutral: 区域
PublicKeyToken: 程序集public密钥
public: 对任何类和成员都公开, 无限制访问;
protected: 仅仅对该类以及该类的派生类公开;
private: 仅仅对该类公开;
internal: 只能值包含该类的程序集中访问该类(只是单独的项目,而不是整个解决方案)
主互操作程序集(PIA)指的是官方发布的互操作程序集,如果电脑中安装了PIA,当你添加对类库的引用时,那么Visual Studio会自动加载PIA,微软为Office应用程序提供了PIA,如EXcel PIA就是Microsof.Office.Interop.Excel.dll,其他应用程序也类似。详见:http://msdn.microsoft.com/zh-cn/library/aax7sdch(v=vs.110).aspx
.NET 反射,为测试方法加了Attribute
throw e; //CLR认为这里是异常的起始点
throw; //CLR不会重新设置异常的起始点
Typeof()是运算符而GetType是方法
GetType()是基类System.Object的方法,因此只有建立一个实例之后才能够被调用(初始化以后)
Typeof()的参数只能是int,string,String,自定义类型,且不能是实例
public class c{ public c(string a) : this() {;}; public c() {;} } 这个构造函数有用吗?
先调用了this(),即无参构造函数,再调用了自身的有参的构造函数。
因为未对a参数进行处理,故无用。
This 用于调用当前实例,无法在 static 方法中调用 this。
aspx <form method=”post” action=”test.aspx”> <input name=”Button1” type=”submit” /> </form> Cs protected void Page_Load(object sender, EventArgs e) { if (Request["Button1"] != null) { //Button1_OnClick Function Code } }
页面数据从客户端通过Form的Post方法传输到服务器端的过程叫做PostBack。
· 什么叫作ViewState?是什么编码?加密了吗?到底是谁在使用ViewState?
保存服务器控件在PostBack时状态不变的技术叫做ViewState。这些状态信息被保存在前台的hidden元素中。默认为Base64编码,默认不会ViewState被加密。在页面中所有开启了ViewState的服务器控件会使用到它。 参考
Machinekey是添加在web.config中<system></system>之间的一个标签。它保证cookies、viewstate加密解密时的数据不会被篡改。参考
Process:优点:进程内。速度比较快,但比较难适应大型应用。
ASP.NET State Service: ASP.NET状态服务。速度,容量上折中。如果使用专用的状态服务器则可以扩展。
SQL Server Session State Management: 速度较慢。但可靠性是最强的。而且也有很高的扩展性,适合大型应用。
当使用线程池中的线程进行异步请求操作时,多个请求间的线程是能够重用的。每个HttpRequest都有自己的线程。当线程重用时,应该使用Thread Local存储。
检查ContentType即可。更安全的做法是解析HttpHandler。
用户输入URL,路由将该次请求转到DNS服务器,DNS服务器将请求转向URL所指向的服务器IP,如果IIS中某个站点包含所请求主机头信息,则请求成功。
服务器在告诉客户端,需要将需要一些服务器必要信息存成cookies保存在客户端中,而每次客户端访问服务器时会将cookies中的信息通过请求发送给服务器。滥用的例子比如:Cookies中保存敏感信息,用户密码。
验证用户输入的所有内容,保证服务器的安全性和健壮性。
Header共包括通用头、请求消息、响应消息及消息实体等数据。
Get方法为URL传值,POST为Form表单传值。
200 访问成功、301 永久重定向、302暂时重定向、304服务器已缓存、404访问资源不存在、500服务器出错、504 网关超时。
if-not-modified-since及 last-modified是保存在Request http header中的两个信息,客户端在访问资源时,对比两个信息,就能确定需要读取缓存文件还是更新本地缓存文件。Response.Content.Headers
Explain <@OutputCache%> and the usage of VaryByParam, VaryByHeader.
VaryByCustom,我们可以自定义输出缓存要求的任意文本。除了在OutputCache指令里面申明该属性之外,我们还得在应用程序的 global.asax 文件的代码声明块中,重写GetVaryByCustomString 方法来为自定义字符串指定输出缓存的行为。
Eg:
<%@ OutputCache VaryByParam="none" VaryByCustom="CategoryPageKey" Location="server" Duration="43200" %>
这里的VaryByCustom定义的为CategoryPageKey,那么在global.asax里面我们必须定义CategoryPageKey这个字符创输出缓存的行为,见下面代码。
public override string GetVaryByCustomString(HttpContext context, String arg) { … }
提供避免元素命名冲突的方法
DOM是一种与浏览器,平台,语言无关的接口,使你可以访问页面其他的标准组件。 DOM解决了Netscape的Javascript和Microsoft的Jscript之间的冲突,给予web设计师和开发者一个标准方法,让他们来访问他们站点中的数据、脚本和表现层对像。
DOM尺寸不受限制。
它由一组非专有的 Web 服务规范以及对这些旨在促进互操作性的规范的说明和修正组成
为相关Web服务更好的一起互操作的使用提供了实现的指导方针
<?xml version="1.0" encoding="UTF-8"?> <note> <to>a</to> <from>b</from> </note>
数据本身应当存储在元素中,而有关数据的信息(元数据)应当存储在属性
属性不能很好地保持原文的结构
元素允许包括元元数据(有关信息的更深层次的信息)。
每个人对元数据和非元数据的理解是不一样的。
面对以后的变化,元素更具扩展性。
对于非常简单并且不随文档改变其形式的信息,使用属性较好。特别是样式信息和链接信息,作为属性执行起来很顺利
格式完好的XML不是有效的xml
不仅要格式完好而且还要遵循一定的顺序规则
格式完好的(well-formed)XML文档包括:起始标签和结束标签应当匹配,结束标签是必不可少的;大小写应一致:XML对字母的大小写是敏感的,和是完全不同的两个标签,所以结束标签在匹配时一定要注意大小写一致;元素应当正确嵌套:子元素应当完全包括在父辈元素中。
有效的(valid)XML文档是指一个遵守XML语法规则,并遵守相应DTD文件规范的XML文档。
XmlReaderSettings settings = new XmlReaderSettings(); settings.ValidationEventHandler += new ValidationEventHandler(this.ValidationEventCallBack); settings.ValidationType = ValidationType.Schema; settings.Schemas serch= schemaSet;
这个会递归搜索全部的Document节点,通常消耗会比较大。除非真的需要检索所有叫mynode的节点,那就比较好。
XmlReader 是一个只进、只读的游标。 它提供了对输入的快速和非缓存的流式访问。 它可以读取流或文档。 它使用户可以提取数据,并跳过对应用程序没有意义的记录。 较大的差异在于 SAX 模型是一个“推送”模型,其中分析器将事件推到应用程序,在每次读取新节点时通知应用程序,而使用 XmlReader 的应用程序可以随意从读取器提取节点。
XPathDocument 类读取 XML 文档-在内存中的快速只读表示形式
可编辑的 XmlDocument 类读取 XML 文档
XML片段通常不是一个完全符合标准的XML文档,可能没有根节点,比如:“<foo></foo><bar></bar>”。XML文档通常有一个根节点和一些由标记组成的内容。比如:“<root><foo></foo><bar></bar></root>”
规范化形式的XML是XML规范的一个子集。任何XML文档都可以转换为规范化形式的XML,因此将特定类型的微小差异去除却仍是该XML文档。
XML InfoSet是W3C规范,用于描述一组数据集的抽象数据模型。XML DOM是InfoSet的一个实例。
DTD通过合法元素和属性列表定义XML文档的文档结构。XSD描述XML文档的文档结构。
支持。设置XmlReaderSettings.DtdProcessing属性为DtdProcessing.Parse。设置XmlReaderSettings.ValidationType属性为ValidationType.DTD。
是的。