.NET工作准备--03进阶知识

(已过时)

高级特性,多线程编程,单元测试;

第一部分 .net高级特性
1.委托:提供安全的函数回调机制;
*基本原理:与C++中的函数指针相似;安全--它和其他所有.net成员一样是一种类型,任何委托都是System.Delegate的某个派生类对象;

System.Object->SystemDelegate(ISerializable,ICloneable)->System.MultiCastDelegate

->Delegate T;
public delegate void TestDelegate(int
i)定义一个委托,内部包含invoke方法(由编译器自动完成);委托的调用其实就是执行类定义委托时生成的Invoke方法;
总结:每个委托至少包含一个指向回调方法的指针,该方法可以是实例方法,也可以是静态方法。委托实现回调方法的机制,方便使用;
*委托回调静态方法和实例方法的区别;
当委托绑定静态方法时,target为null;绑定实例方法是,target指向该实例方法所属类型的一个实例对象;

*什么是链式委托:指一个由委托组成的链表,而不是指另一个特殊的委托;prev,当一个委托被调用时,所有链表上的该委托的后续委托均被顺序执行;

*链式委托的执行顺序:按照委托链上的顺序从当前委托开始依次向后执行。如果有需要,可以通过GetInvocationList()来获得委托链上所有需要执行的委托,并且按照任何希望的顺序去执行;

*可否定义有返回值的方法的委托链:委托可以是带有返回值的方法,但多于一个待返回值的方法被添加到委托链是,程序员需要手动调用每一个委托链上的方法;

*委托的应用场合:任务的执行者把细节工作进行再分配,执行者确切地知道什么工作将要被执行,但却把执行细节委托给其他组件,方法或程序集;一些简单的重点记录:(给个程序集中有多个模块的例子)

2.事件(Event)
定义:是一种使对象或类能够提供通知的成员,客户端可以通过提供事件处理程序为相应的事件添加可执行代码;

event标记__委托类型(如EventHandler)__声明的事件对象;
使用事件的步骤:
如果需要,定义一个派生自System.EventArgs的参数类型;

ConsoleEventArgs
在事件的管理类型中定义事件的私有成员;               
ConsoleManagsder.ConsoleEvent
通知事件订阅者;                                    
ConsoleManager.SendConsoleEvent
事件使用客户端订阅/取消订阅事件;                    
Log
补充StreamWriter,StreamReader,各种Stream:
using(FileStream fs = File.Create(...)){}
using(StreamWriter sw =info.AppendText()){}
*事件和委托有何联系?
实际上,事件就是就是一个委托类型,当程序员定义一个事件的时候,实际上是定义了一个特殊的委托成员。它没有返回值,有固定的两个参数
sender,EventArgs;而事件的使用者订阅事件时,本质就是把事件处理方法加入到委托链表中;声明event时默认会添加一对针对特定委托的
add/remove方法;

*如何设计一个带很多事件的类型?使用EventHandlerList(System.ComponentModel);
注意:考虑线程同步措施;每个事件定义一套成员--事件的委托原型,事件的订阅和取消订阅方法,定义事件的专用参数类型;减少多事件类型的大小,但代码量增加;

*用代码表示如下情形:猫叫,老鼠逃跑,主人惊醒<==>猫叫被老鼠和主人订阅;

3.反射
*反射的原理和实现它的基石:反射是一种动态分析程序集,模块,类型,字段等目标对象的机制,它的实现依托于元数据(基石)。元数据是存储在PE文件中的数据块,他详细记录了程序集或模块内部的结构,引用类型,程序集清单.TypeDef,TypeRef&AssemblyRef,Assembly;

*.net提供哪些类型来实现反
射:Assembly,AssemblyName,EventInfo,LocalVariableInfo,ManifestResourceInfo,MemberInfo,MethodBase,MethodBody,Module,ParameterInfo,PropertyInfo;

*如何动态的发射程序集:动态的生成一个程序集。而不仅仅是分析程序经济或者生成程序集对象;在System.Reflection.Emit命名空间
下,定义了一系列用于动态发射程序集,模块,类型,方法等元素的中间代码。这些类型的主要使用者是编译器,特殊反射工具或者脚本解释器.

AssemblyBuilder,ConstructorBuilder,CustomerAttributeBuilder,EnumBuilder,EventBuilder,FieldBuilder,GenericTypeParameterBuilder,ILGenerator,LocalBuilder,MethodBuilder,OpCodes,ParameterBuilder,PropertyBuilder,TypeBuilder;

//步骤:
在当前appDomain中定义新程序集: AppDomain myDomain = Thread.GetDomain();
定义模块:                    
assemblyBuilder.DefineDynamicModule();
定义模块中的类型:             
Typebuilder addClass=assemblyModule.DefineType();
定义公共构造方法及其参数      
Type[] ctorParams = new Type[]{typeof(long),typeof(long)};
           
构造方法中间代码  
ctorIL.Emit(OpCodes.Ldarg_0);
动态发送程序集:
object  ptInstance=Activator.CreateInstance(type,
ctorParams);
MethodInfo info = type.GetMethod("GetResult", new
Type[0]);//通过方法名和返回值类型得到方法;
OpCodes类型包含大多数需要使用的中间代码指令;
注意:新的程序集发射是直接把中间代码在内存中生成一种机制,而不是在物理硬盘上生成代码的机制;
*利用反射来实现工程模式,动手;

//针对每一个product做相应的Attribute,针对product系列做Attribute,还是需要参考
   
[AttributeUsage(AttributeTargets.Class)]
    public class
ProductAttribute : Attribute
    {RoomPart
_myRP = new RoomPart();
       
public ProductAttribute(RoomPart rp)
       
{_myRP = rp;  }
       
public RoomPart MyRoomPart
       
{get{ return _myRP;}
       
} }

[AttributeUsage(AttributeTargets.Interface)]
    public class
ProductListAttribute : Attribute
    {Type[]
_mylist;
       
public ProductListAttribute(Type[] productList)
       
{_mylist = productList;}
       
public Type[] MyProductList
       
{get { return _mylist; } }
    }
public IProduct  Produce(RoomPart rp)
{//通过反射,从IProduct接口获得属性,从而获得所有的产品零件列表
   
ProductListAttribute pla =
(ProductListAttribute)Attribute.GetCustomAttribute(typeof(IProduct),
typeof(ProductListAttribute));
   
//遍历所有的实现产品零件类型
    foreach
(Type type in pla.MyProductList) {
       
ProductAttribute pa =
(ProductAttribute)Attribute.GetCustomAttribute(type,
typeof(ProductAttribute));
       
if (rp == pa.MyRoomPart) {
          
object pro = 
Assembly.GetExecutingAssembly().CreateInstance(type.FullName);

return pro as IProduct;
       
}
       
return null;}}
*用较小内存保存Type,Field,Method信息:
System.RuntimeTypeHandle和System.Type的转换;Type.GetTypeHandle(type),Type.GetTypeFromHandle(typeHandle);

System.RuntimeMethodHandle和System.Reflection.MethodInfo的转换;
System.RuntimeFeildHandle和System.Reflection.FieldInfo的转换;

4.特性
特性机制帮助程序员以声明的方式进行编程,而不再需要考虑实现的细节;这样的机制有点类似AOP的编程概念;
*什么是特性,如何自定义一个特性?
特性是一种有别于普通命令式编程的编程方式,通常称为声明式编程方法。所谓声明式编程就是程序员秩序声明某个模块会具有怎么样的特性,而无需关心实现;特
性在被编译时,和传统的命令式代码不同,它会被以二进制数据的方式写入模块文件的元数据中,而在运行时被解读使用。特性也是经常被反射机制应用的元素,因
为它本身是以元数据形式存放的.

自定义特性:本质就是定义一个继承自System.Attribute类的类型;
使用需要注意:特性名称用Attribute结尾;为了方便,使用特性时可以省略最后的Attribute;特性类型自身也可以添加其他特性,如[AttributeUsage()].

*.net特性可以在那些元素上应用?
Assembly,Module,Class,Struct,Enum,Constructor,Method,Property,Field,Event,Interface,Parameter,Delegate,ReturnValue,GenericParameter;

对于类型,结构等元素,特性的使用可以添加在其定义上方,而对于程序集、模块等元素的特性来说,则需要显示地告诉编译器这些特性的作用目标;如:[assembly:MyAttribute];

可以使用AttributeUsage(AttributeTargets..)来限定特性的使用范围;
*获取元素已经申明特性的方法:
System.Attribute.IsDefined;
System.Attribute.GetCustomerAttribute()/GetCustomerAttributes;会查找指定特性以及其派生特性,并且会实例化.若声明多次,则报AmbiguousMatchException异常;

System.Reflection.CustomAttributeData--GetCustomAttributes;该类型使用不会导致特性的实例化,适合安全性要求高的系统;

注意:读者使用这些方法时,需要注意是否需要实例化特性,因为这意味着元数据中的字节流将被执行,这可能是一个安全隐患。(未理解)

*一个元素能否重复声明同一特性?使用AttributeUsageAttribute的AllowMultiple属性,设置为True;

5.名企面试真题
*.什么是反射?一种动态分析程序集,模块,类型,方法,字段等目标对象的机制,它依托于元数据;

*.在什么情况下使用过委托(答的都不是很准确)?需要由使用者而不是设计者提供回调方法时使用。

任务的执行者把细节任务进行再分配,执行者确切知道什么工作将要被执行,但却把执行细节委托给其他的组件,方法或程序集。
*.请概述事件与委托有什么不同?事件是一种指定格式的委托,要求它没有返回值,参数固定为object-sender,EventArgs-args,它自带add/remove方法,由于在委托链上添加和删除回调方法(事件处理方法);

*.你最常用的特性有哪些?首先是特性的特性:[AttributeUsage],[Serializable]等;
*.介绍一个你设计过的自定义特性,为什么要使用特性?
如[target.class]NameAttribute,使用特性有很大的灵活性,比如对工厂设计模式的优化,达到解耦的作用;同时特性是一种声明式的编程方式;

*.反射机制的性能如何,你会在什么情况下使用反射?反射是一种动态的分析程序集,模块,类型,方法等目标对象的机制,它的基石是元数据;其实他就是通过调用方法对元数据进行操作,使用它会使程序性能下降。

当我需要对暂时未知的程序集,类型等目标对象进行操作时,我会使用。因为此时是没用方法名称,字段名称等内容的。在一些特殊情况下,我还会有Reflection.Emit动态的在内存中创建程序集;

*.请问动态的发射代码有何作用?可以直接在内存中创建程序集,不用驻留在硬盘;它一般使用在编译器,特殊反射工具,脚本解释器中;

*.请用代码描述肯德基排队购买场景;自己做一个简版的;假设一个收银,来人加入队列,买好离开队列;不涉及多线程,算法选择等内容;

*.请介绍程序集元数据包含哪些内容?TypeDef,TypeRef&AssemblyRef,Assembly清单;

第二部分 .net多线程编程
1.多线程编程的基本概念;
*解释操作系统层面上的进程和线程
进程:拥有自己的程序块,独占的资源和数据,并且可以被操作系统调用;
线程:是一个可以被调度的单元,并且维护自己的堆栈和上下文环境;
简单来说进程代表了一个正在运行的应用程序实体,而进程可以包含一个或多个线程;
线程和进程最大的区别在于隔离性问题,每个进程被单独地隔离,拥有自己的内存块,独占资源和运行数据,进程间的交互也是相当困难的.而同一进程内的所有线程共享资源和内存块,并且一个线程可以访问,结束同一进程内的其他线程;

*多线程程序在OS中是并行执行的么
线程调度:抢占式和非抢占式,例如Windows--属于同时采用抢占式和非抢占式模式。对于那些优先级高的线程,采用非抢占,对于普通线程,采用抢占模式快速切换;

在单个CPU的架构上,任何时候只能存在一个运行的线程,OS用过快速的调度轮换让使用者感觉多线程同时执行。而在多CPU架构上,则可能存在并行运行的线程,这取决与线程间是否争用资源;(windows提出一个超线程的概念,就是虚拟CPU,多通道(Intel)?)

*什么是迁程?可以视为一个轻量级线程,拥有自己的栈和上下文(寄存器)状态,调度由程序员编码控制;
在.net运行框架中新建Thread,并不一定保证在OS层面上产生了一个真正的线程;想想(os线程,用户线程);
实际上,.net中的线程可能是一个线程,一个迁程甚至一个.net自定义的结构;
补充:所谓CLR寄宿,指CLR框架运行在某个应用程序上而非字节在操作系统上。常见的有asp.net,sqlserver2005.

2.net中的多线程编程;
*如何在.net中手动控制多个线程;创建一个Thread类型对象并不意味着生成一个线程,需要调用Start才生成;
控制线程的状态:

*如何使用.net线程池;
所谓的.net线程池,是指由CLR管理的线程池,而不是指线程池是由.net框架引入的;CLR管理代码负责整理并处理线程的需求,策略可变,投递需求较多时,可能多个线程同时运行处理需求,反之,只创建单线程。

线程池中运行的线程都是后台线程,IsBackground为true;所谓后台线程指这些线程的运行不会阻碍应用程序的结束;

System.Threading.ThreadPool:每个进程都拥有一个线程池,.net提供管理机制,用户只需要把线程需求插入到线程池即可;

static bool
QueueUserWorkItem(WaitCallBack--委托类型,接受Object参数,无返回值--callback)

static bool QueueUserWorkItem(WaitCallBack callback, Object
state)
static bool UnsafeQueueUserWorkItem(WaitCallBack callback, Object
state):不会将主线程权限限制传递给辅助线程,可能会提升辅助线程的权限,产生安全漏洞;
*如何查看和设置线程池的上下限;一般不需要修改
ThreadPool.Get/Set Max/Min/Available Threads;
*如何定义线程独享的全局数据;
TLS:本地线程存储;静态变量扮演了全局(appDomain)可见的数据角色,一个static变量同一appDomain的线程均可访问,若希望只有当前线程可对其访问修改的变量,就需要TLS的概念;

方式一,使用LocalDataStoreSlot:它本身不是线程独显的,但初始化一个该对象意味着在应用程序域内的每个线程上均分配一个数据插槽;

LocalDataStoreSlot ldss  =
thread.AllocateDataSlot();
Thread.SetData(ldss, Thread.CurrentThread.ManagedThreadId);
Thread.GetData(ldss);
方式二,ThreadStaticAttribute使用
*如何使用异步模式读取一个文件;
异步模式:是一种处理流类型时经常用到的模式,读写文件,网络传输,读写数据库,甚至可以异步模式来做任何计算工作。相对于收到编写线程代码,异步模式是一种高效的编程模式;

指启动一个操作后可以继续执行其他工作,而不必等待操作的结束。
在.net中,很多类型都支持异步模式编程,以下为4个步骤:
调用一个形似BeginXXX的方法,表明开始异步执行某操作;
在调用了BeginXXX方法后,主线程可以继续执行任意的代码,而无需关心异步操作情况;
以异步聚集技巧来查看异步操作的结果;
调用EndXXX来表示一个异步操作结果;
异步模式区别于线程池机制的地方:
直接调用EndXXX方法,如果异步操作还未执行,主线程会被阻止直到一步操作结束;
查看调用BeginXXX后得到的IAsyncResult对象IsCompleted属性;
在调用BeginXXX时传入操作结束后需要执行的方法,同时把执行异步操作的对象传入以便执行EndXXX方法;(未理解)
尽量使用第三种技巧:主线程负责开始异步读取并且传入狙击时需要的方法和状态对象;
 using (FileStream fs =
File.Create(_fileName))
{string content = @"宝山是个SB,哈哈!";
  byte[] contentByte =
Encoding.Default.GetBytes(content);
  fs.Write(contentByte, 0,
contentByte.Length);}
//开始异步读取文件内容,注意这儿Fs的生命周期是有限的。
using (FileStream fs = new FileStream(_fileName, FileMode.Open,
FileAccess.Read, FileShare.Read, 1024,
FileOptions.Asynchronous))
               
{byte[] data = new byte[1024];
                   
AsyncReadClass arc = new AsyncReadClass(data, fs);
                   
fs.BeginRead(data, 0, 1024, FinishRead, arc);
//主线程执行一些其他操作
                   
Thread.Sleep(1000 * 3);
                   
Console.Read();}
 private static void FinishRead(IAsyncResult
ar)
       
{
           
AsyncReadClass arc = ar.AsyncState as AsyncReadClass;
           
//让异步读取占用的资源释放
           
int length = arc.Fs.EndRead(ar);//注意对象的生命周期}

*如何阻止线程执行上下文的传递;
同一进程中线程虽然共享资源和内存块,但仍然拥有自己的上线问,在.net中,线程的上下文有流动的特性;
线程执行上下文的内容:安全上下文,调用上下文,同步上下文,本地化上下文,事务上下文,CLR宿主上下文;
上下文的流动:Thread thread;thread.Start();thread.join()//阻塞当前线程;
如何阻止上下文的流动:线程执行的上下文是所有线程的一个包装,在通常情况下,当前线程的执行上下文会流动到新建线程之中。程序员可以使用定义在
System.Threading.ThreadPool类型的UnsafeQueueUserWorkItem方法和定义在
ExecutionContext类型中的SuppressFlow方法来阻止这种流动。注意这样虽然可以提高效率,但会降低安全性;

3.多线程程序的线程同步
*什么是同步快和同步快索引;
.net团队在设计基本框架时已经考虑了线程同步的问题,采用了折中的方式:为每个对内存对象分配一个索引,该索引中只存在一个表明数组内索引的整数。
在.net加载时会新建一个同步块数组,每当某个对象需要被同步时,.net会为其分配一个同步块,并且把该同步块在同步数组中的索引加入对象的同步块索
引中;

当一个线程试图使用该对象进入同步时,会检查该对象的同步索引,如果索引为负数则会在同步块数组中寻找或者新建一个同步块,并且把同步块索引值放入该对象
的同步块索引中,如果不为负值,则找到该同步块,并且检查是否被其他线程使用,如果有进入等待状态,如果没用则申明使用该同步块.

进入和退出同步:System.Threading.Monitor.Enter/Exit;
*C#中的lock关键字有何作用;
lock等价于Monitor.Entry/Exit;
在通常情况下,lock一个私用引用成员变量来完成成员方法的线程同步,使用一个私有静态引用变量来完成静态方法的线程同步;

*是否可以使用值类型对象来实现线程同步?不能,会出现严重错误,Monitor相关方法使用时会出现拆装箱,每一次堆内的对象均会改变,出现严重错误。所以应该使用lock,而不要使用Monitor.Entrr/Exit;

*可否对引用类型自身进行同步;可以,但这样的程序缺乏健壮性(lock(this),lock(Typeof(...))),当某个类型使用者恶意地长期占用对象的同步块时,所有的其他对象会死锁;

*什么是互斥体,Mutex类型,Monitor类型的功能有何区别;(WaitHandle(所有封装的内核同步对象的的抽象基类),类似的还有Semaphone,
EventWaitHandler);
Mutex.WaitOne();Mutex.Close();Mutex.ReleaseMutex();
Mutex使用OS内核对象,Monitor在.net框架实现,mutex效率低下(10倍,用户态->系统态);
Monitor只能同步一个AppDomian中的线程,而Mutex可以跨越Process;
4.名企真题;
*进程与线程如何理解?操作系统中的进程拥有自己独立的内存空间(包含数据块,程序块),如Win32(分配4G的虚拟内存空间),进程可以被操作系统调
度,简单来说,一个进程代表了一个正在运行的应用程序实体,可以包含一个或多个线程;线程是一个可以被调度的单元,维护自己独立的堆栈和上下文环境;

进程与线程的最大区别是隔离性,每个进程独立的运行,拥有自己的内存块,独占资源,相互间的交互困难;而一个进程中的多个线程可以共享数据和内存块,一个线程可以访问,结束同一进程中另外的线程;

*根据线程安全的相关知识,分析当调用test时,i>10是否会引起死锁:
public void test(int i){
lock(this){
if(i>10){
i--;
test(i);
}}}//首先不建议使用this之中lock方式;//不会死锁,因为传的是值类型;(未OK)
*后台线程与一般线程有何区别:
前台线程能阻止应用程序的终结,一直到所有的前台线程终止后,CLR才能关闭应用程序。后台线程又被称为守护线程,它被CLR认为是程序执行中可以做出牺牲的途径,即任何时候都可以被忽略,因此,如果所有的前台线程终止,应用程序卸载时,所有的后台线程也会被自动终止.

*一共有几种方法在多线程间共享数据?(这儿的共享其实就是指的如何同步)lock,mutex;
*使用lock和mutex的区别:效率上lock高很多,但mutex因为是os内核对象所以可以实现多进程间的同步;
*是否可以对值类型使用lock?不能,CLR的机制是在所有的堆对象中分配一个同步块索引,值类型没有;
*你会在什么时候考虑使用多线程?比如考虑到相应速度,不希望因为资源的阻塞而影响用户的使用;
*使用Thread类型新建的线程是否来自线程池?必须不是,ThreadPool.QueueUseWorkItem();

第三部分 .net单元测试
1.单元测试的基本概念;
*简述单元测试概念和优点;
*举例说明TDD开发方式流程;
*编程阶乘功能模块测试用例;

2.使用NUnit进行单元测试;
*如何使用NUNIT进行单元测试;
*如何对测试用例进行分类;
*解释SetUp,TearDown;

3.名企面试真题;

时间: 2024-10-05 03:17:51

.NET工作准备--03进阶知识的相关文章

Spring实战3:装配bean的进阶知识

主要内容: Environments and profiles Conditional bean declaration 处理自动装配的歧义 bean的作用域 The Spring Expression Language 在装配bean—依赖注入的本质一文中,我们探讨了Spring的三种管理bean的方式:自动装配.基于JavaConfig.基于XML文件.这篇文字将探讨一些Spring中关于bean的管理的高级知识,这些技能你可能不会每天都用,但是非常重要. 3.1 Environments

Python学习之旅—面向对象进阶知识:类的命名空间,类的组合与继承

前言 上篇博客笔者带领大家初步梳理了Python面向对象的基础知识,本篇博客将专注于解决三个知识点:类的命名空间,类的组合以及面向对象的三大特性之一继承,一起跟随笔者老看看今天的内容吧. 1.类的命名空间 在上一篇博客中,我们提到过对象可以动态添加属性,一起来回忆下昨天的知识点,看如下的代码: class A: pass a = A() a.name = 'alex' print(a.name) 这里我们手动为a对象添加了一个属性name,然后直接打印可以得到a对象的名称.通过这个例子,我们可以

redis快速入门-进阶知识

前言 前面我们已经学习了redis的数据类型,接下来将简单学习下redis的事务,排序,管道,优化存储空间以及管理等知识. 事务 事务的概念在此不赘述,学过数据库原理的都应该知道. redis的事务:先将属于一个事务的命令发送给redis,然后再让redis依次执行这些命令: MULTI //开始一个事务 //事务的命令 EXEC //执行事务 EXEC告诉redis将等待执行的事务队列中的所有命令(即刚才所有返回QUEUED的命令)按照发送顺序依次执行. 错误处理 1.语法错误:命令不存在或者

考试备战系列--软考--03综合知识复习

这部分主要是架构师综合知识的介绍,相关系列文章如下所示. 在实际应用中,面对安全威胁,可以通过如下5个方面进行准备:认证鉴别.访问控制.内容安全.冗余回复和审计响应. 相关信息安全标准:TCSEC(美国).ITSEC(欧洲).加拿大(CTCPEC).ISO7498-2-1989标准.我国的信息安全主管部门包括公安部.信息产业部和国家技术标准局. 1.信息系统安全体系 验证(Authentication):验证用户是否可以获得访问权,认证信息包括用户名.用户密码和认证结果. 授权(Authoriz

个人工作总结03

今天是开始的第3天,我的工作总结如下: 一.昨天干了什么? 对查课表功能进行设计,并对图书查询进行更改. 二.今天准备做什么? 今天主要是跟学校教育技术中心的老师要教务网站数据库接口,以及对API Help File进行学习. 三.遇到了什么困难? 图书馆查询功能的实现关键技术还未彻底分析清楚.

Django进阶知识

Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接数据库,并编写数据访问层代码 业务逻辑层去调用数据访问层执行数据库操作 import MySQLdb def GetList(sql): db = MySQLdb.connect(user='root', db='wupeiqidb', passwd='1234', host='localhost') cursor = db.cursor() cursor.

.NET工作准备--02基础知识

(已过时) 框架基础,语法基础,字符串&集合&流,常见类和接口; 02.net基础(重点) -第一部分 框架基础 1.基础概念 CTS(Common Type System),CLS(通用语言规范),CLR(Common Language Runtime); 环境基础-.net framework; 程序集(Assembly),AppDomain:[进程 [CLR  [AppDomain  ]  ]  ] 2.运行机制 * C#--csc.exe-->IL--JIT-->机器码

PHP进阶知识总结

周末梳理了下这段时间看书的一些知识点,进步的过程不仅要实践,还要安排多看书.思考.总结. 只针对知识点进行了罗列和简单说明,很多细节还未整理好,待后面再专门详细写. 基础易忽略概念 PHP是一个支持面向对象开发的语言,而不是一个纯面向对象的语言 PHP5中保留了对var的支持,但会将var自动转换为public 类型检查函数: is_bool() is_integer() is_double() is_string() is_object() is_array() is_resource() i

ASP.NET MVC异步验证是如何工作的03,jquery.validate.unobtrusive.js是如何工作的

在上一篇"ASP.NET MVC异步验证是如何工作的02,异步验证表单元素的创建"中了解了ASP.NET异步验证是如何创建表单元素的,本篇体验jquery.validate.unobtrusive.js异步验证的全过程. 在jquery.validate.unobtrusive.js文件的尾部看到了如下的一个调用: $(function () { $jQval.unobtrusive.parse(document); }); 可见,通过把当前页的document对象传给$jQval.u