ASP.NET网页编程之.NET 4.0中的泛型协变和反变仓酷云
中间码是基于一个虚拟机器。源代码是最高层的,理论上从源代码开始直接编译成本地码能提供最大优化的。而中间码只能是转译成本地码,效率上难免受到损耗。根据虚拟机器所设定的体系结构的特点,和本地机器的差异的多少。随VisualStudio2010CTP表态的C#4和VB10,固然在撑持言语新特征方面走了相称纷歧样的两条路:C#侧重增添前期绑定和与静态言语相容的多少特征,VB10侧重简化言语和进步笼统才能;可是二者都增添了一项功效:泛型范例的协变(covariant)和反变(contravariant)。很多人对其懂得大概仅限于增添的in/out关头字,而对其诸多特征有所不知。上面我们就对此举行一些具体的注释,匡助人人准确利用该特征。背景常识:协变和反变
良多人大概不不克不及很好地舆解这些来自于物理和数学的名词。我们无需往懂得他们的数学界说,可是最少应当能分清协变和反变。实践上这个词来历于范例和范例之间的绑定。我们从数组入手下手了解。数组实在就是一种和详细范例之间产生绑定的范例。数组范例Int32[]就对应于Int32这个底本的范例。任何范例T都有其对应的数组范例T[]。那末我们的成绩就来了,假如两个范例T和U之间存在一种平安的隐式转换,那末对应的数组范例T[]和U[]之间是不是也存在这类转换呢?这就牵涉到了将底本范例上存在的范例转换映照到他们的数组范例上的才能,这类才能就称为“可变性(Variance)”。在.NET天下中,独一同意可变性的范例转换就是由承继干系带来的“子类援用->父类援用”转换。举个例子,就是String范例承继自Object范例,以是任何String的援用都能够平安地转换为Object援用。我们发明String[]数组范例的援用也承继了这类转换才能,它能够转换成Object[]数组范例的援用,数组这类与原始范例转换偏向不异的可变性就称作协变(covariant)。
因为数组不撑持反变性,我们没法用数组的例子来注释反变性,以是我们如今就来看看泛型接口和泛型托付的可变性。假定有如许两个范例:TSub是TParent的子类,明显TSub型援用是能够平安转换为TParent型援用的。假如一个泛型接口IFoo<T>,IFoo<TSub>能够转换为IFoo<TParent>的话,我们称这个历程为协变,并且说这个泛型接口撑持对T的协变。而假如一个泛型接口IBar<T>,IBar<TParent>能够转换为T<TSub>的话,我们称这个历程为反变(contravariant),并且说这个接口撑持对T的反变。因而很好了解,假如一个可变性和子类到父类转换的偏向一样,就称作协变;而假如和子类到父类的转换偏向相反,就叫反变性。你记着了吗?
.NET4.0引进的泛型协变、反变性
方才我们解说观点的时分已用了泛型接口的协变和反变,但在.NET4.0之前,不管C#仍是VB里都不撑持泛型的这类可变性。不外它们都撑持托付参数范例的协变和反变。因为托付参数范例的可变性了解起来笼统度较高,以是我们这里禁绝备会商。已完整可以了解这些观点的读者本人想必可以本人往了解托付参数范例的可变性。在.NET4.0之前为何不同意IFoo<T>举行协变或反变呢?由于对接口来说,T这个范例参数既能够用于办法参数,也能够用于办法前往值。假想如许的接口
InterfaceIFoo(OfT)
SubMethod1(ByValparamAsT)
FunctionMethod2()AsT
EndInterface
interfaceIFoo<T>
{
voidMethod1(Tparam);
TMethod2();
}
假如我们同意协变,从IFoo<TSub>到IFoo<TParent>转换,那末IFoo.Method1(TSub)就会酿成IFoo.Method1(TParent)。我们都晓得TParent是不克不及平安转换成TSub的,以是Method1这个办法就会变得不平安。一样,假如我们同意反变IFoo<TParent>到IFoo<TSub>,则TParentIFoo.Method2()办法就会酿成TSubIFoo.Method2(),底本前往的TParent援用一定可以转换成TSub的援用,Method2的挪用将是不平安的。有此可见,在没有分外机制的限定下,接口举行协变或反变都是范例不平安的。.NET4.0改善了甚么呢?它同意在范例参数的声明时增添一个分外的形貌,以断定这个范例参数的利用局限。我们看到,假如一个范例参数仅仅能用于函数的前往值,那末这个范例参数就对协变相容。而相反,一个范例参数假如仅能用于办法参数,那末这个范例参数就对反变相容。以下所示:
InterfaceICo(OfOutT)
FunctionMethod()AsT
EndInterface
InterfaceIContra(OfInT)
SubMethod(ByValparamAsT)
EndInterface
interfaceICo<outT>
{
TMethod();
}
interfaceIContra<inT>
{
voidMethod(Tparam);
}
能够看到C#4和VB10都供应了迥然不同的语法,用Out来形貌仅能作为前往值的范例参数,用In来形貌仅能作为办法参数的范例参数。一个接口能够带多个范例参数,这些参数能够既有In也有Out,因而我们不克不及复杂地说一个接口撑持协变仍是反变,只能说一个接口对某个详细的范例参数撑持协变或反变。好比如有IBar<inT1,outT2>如许的接口,则它对T1撑持反变而对T2撑持协变。举个例子来讲,IBar<object,string>可以转换成IBar<string,object>,这里既有协变又有反变。
在.NETFramework中,很多接口都仅仅将范例参数用于参数或前往值。为了利用便利,在.NETFramework4.0里这些接口将从头声明为同意协变或反变的版本。比方IComparable<T>就能够从头声明成IComparable<inT>,而IEnumerable<T>则能够从头声明为IEnumerable<outT>。不外某些接口IList<T>是不克不及声明为in或out的,因而也就没法撑持协变或反变。
上面提起几个泛型协变和反变简单疏忽的注重事项:
1.唯一泛型接口和泛型托付撑持对范例参数的可变性,泛型类或泛型办法是不撑持的。
2.值范例不介入协变或反变,IFoo<int>永久没法酿成IFoo<object>,不论有没有声明out。由于.NET泛型,每一个值范例会天生专属的关闭机关范例,与援用范例版本不兼容。
3.声明属性时要注重,可读写的属性会将范例同时用于参数和前往值。因而只要只读属性才同意利用out范例参数,只写属功能够利用in参数。
协变和反变的互相感化
这是一个相称风趣的话题,我们先来看一个例子:
InterfaceIFoo(OfInT)
EndInterface
InterfaceIBar(OfInT)
SubTest(ByValfooAsIFoo(OfT))"对吗?
EndInterface
interfaceIFoo<inT>
{
}
interfaceIBar<inT>
{
voidTest(IFoo<T>foo);//对吗?
}
你能看出上述代码有甚么成绩吗?我声了然inT,然后将他用于办法的参数了,统统一般。但出乎你料想的是,这段代码是没法编译经由过程的!反而是如许的代码经由过程了编译:
InterfaceIFoo(OfInT)
EndInterface
InterfaceIBar(OfOutT)
SubTest(ByValfooAsIFoo(OfT))
EndInterface
interfaceIFoo<inT>
{
}
interfaceIBar<outT>
{
voidTest(IFoo<T>foo);
}
甚么?明显是out参数,我们却要将其用于办法的参数才正当?初看起来切实其实会有一些惊异。我们必要费一些周折来了解这个成绩。如今我们思索IBar<string>,它应当可以协酿成IBar<object>,由于string是object的子类。因而IBar.Test(IFoo<string>)也就协酿成了IBar.Test(IFoo<object>)。当我们挪用这个协变前方法时,将会传进一个IFoo<object>作为参数。想想,这个办法是从IBar.Test(IFoo<string>)协变来的,以是参数IFoo<object>必需可以酿成IFoo<string>才干满意原函数的必要。这里对IFoo<object>的请求是它可以反变成IFoo<string>!而不是协变。也就是说,假如一个接口必要对T协变,那末这个接口一切办法的参数范例必需撑持对T的反变。同理我们也能够看出,假如接口要撑持对T反变,那末接口中办法的参数范例都必需撑持对T协变才行。这就是办法参数的协变-反变交换准绳。以是,我们其实不能复杂地说out参数只能用于前往值,它的确只能间接用于声明前往值范例,可是只需一个撑持反变的范例帮忙,out范例参数就也能够用于参数范例!换句话说,in参数除间接声明办法参数以外,也仅能借助撑持协变的范例才干用于办法参数,仅撑持对T反变的范例作为办法参数也是不同意的。要想深入了解这一观点,第一次看大概会有点绕,倡议有前提的情形下多举行一些实行。
方才提到了办法参数上协变和反变的互相影响。那末办法的前往值会不会有一样的成绩呢?我们看以下代码:
InterfaceIFooCo(OfOutT)
EndInterface
InterfaceIFooContra(OfInT)
EndInterface
InterfaceIBar(OfOutT1,InT2)
FunctionTest1()AsIFooCo(OfT1)
FunctionTest2()AsIFooContra(OfT2)
EndInterface
interfaceIFooCo<outT>
{
}
interfaceIFooContra<inT>
{
}
interfaceIBar<outT1,inT2>
{
IFooCo<T1>Test1();
IFooContra<T2>Test2();
}
我们看到和方才恰好相反,假如一个接口必要对T举行协变或反变,那末这个接口一切办法的前往值范例必需撑持对T一样偏向的协变或反变。这就是办法前往值的协变-反变分歧准绳。也就是说,即便in参数也能够用于办法的前往值范例,只需借助一个能够反变的范例作为桥梁便可。假如对这个历程还不是出格分明,倡议也是写一些代码来举行实行。至此我们发明协变和反变有很多风趣的特征,以致于在代码里in和out都不像他们字面意义那末好了解。当你看到in参数呈现在前往值范例,out参数呈现在参数范例时,万万别晕倒,用本文的常识便可破解个中奇妙。
总结
经由本文的解说,人人应当已开端懂得的协变和反变的寄义,可以分清协变、反变的历程。我们还会商了.NET4.0撑持泛型接口、托付的协变和反变的新功效和新语法。最初我们还套了论的协变、反变与函数参数、前往值的互相感化道理,和由此发生的奇奥写法。我但愿人人看了我的文章后,可以将这些常识用于泛型程序计划傍边,准确使用.NET4.0的新增功效。祝人人利用兴奋!
本文出自:http://www.ckuyun.com/Ninputer/archive/2008/11/22/generic_covariant.html
有理由相信是能提供更出色的性能。很多平台无法支持复杂的编译器,因此需要二次编译来减少本地编译器的复杂度。当然可能做不到net网页编程编译器那么简易。 ASP.NET:ASP.net是Microsoft.net的一部分,作为战略产品,不仅仅是ActiveServerPage(ASP)的下一个版本;它还提供了一个统一的Web开发模型,其中包括开发人员生成企业级Web应用程序所需的各种服务。ASP.NET的语法在很大程度上与ASP兼容,同时它还提供一种新的编程模型和结构,可生成伸缩性和稳定性更好的应用程序,并提供更好的安全保护。 微软又推出ASP.NET。这不是ASP的简单升级,而是全新一代的动态网页实现系统,用于一台WEB服务器建立强大的应用程序。是微软发展的新体系结构.NET的一部分,是ASP和.NET技术的结合。 可以通过在现有ASP应用程序中逐渐添加ASP.NET功能,随时增强ASP应用程序的功能。ASP.NET是一个已编译的、基于.NET的环境,可以用任何与.NET兼容的语言(包括VisualBasic.NET、C#和JScript.NET.)创作应用程序。另外,任何ASP.NET应用程序都可以使用整个.NETFramework。开发人员可以方便地获得这些技术的优点,其中包括托管的公共语言运行库环境、类型安全、继承等等。 在asp.net虚拟主机的服务提供商中,目前首推的是CNNIC的其中一家域名注册机构---时代互联(www.now.net.cn),他们早在2001年微软刚推出Asp.net时就推出了对应的Asp.net虚拟主机了,经笔者的使用测试,他提供的Asp.net性能非常的稳定,版本也会定期的更新,目前他的 ASP在执行的时候,是由IIS调用程序引擎,解释执行嵌在HTML中的ASP代码,最终将结果和原来的HTML一同送往客户端。 它可通过内置的组件实现更强大的功能,如使用A-DO可以轻松地访问数据库。 ASP是把代码交给VBScript解释器或Jscript解释器来解释,当然速度没有编译过的程序快了。 是目前ASP在UNIX/Linux上的应用可以说几乎为0)。所以平台的局限性和ASP自身的安全性限制了ASP的广泛应用。 我觉得什么语言,精通就好,你要做的就是比其他80%的人都厉害,你就能得到只有20%的人才能得到的高薪。 CGI程序在运行的时候,首先是客户向服务器上的CGI程序发送一个请求,服务器接收到客户的请求后,就会打开一个新的Process(进程)来执行CGI程序,处理客户的请求。CGI程序最后将执行的结果(HTML页面代码)传回给客户。 在调试JSP代码时,如果程序出错,JSP服务器会返回出错信息,并在浏览器中显示。这时,由于JSP是先被转换成Servlet后再运行的,所以,浏览器中所显示的代码出错的行数并不是JSP源代码的行数。 ASP.net的服务器,要求安装一个.net环境,当然我这里指的是windows系统,顺便点一下,.net只能放在windows环境里来运行。Asp.net1.1的就装Framework1.1,Asp.net2.0的就装Framework2.0。 逐步缩小出错代码段的范围,最终确定错误代码的位置。 能产生和执行动态、交互式、高效率的站占服务器的应用程序。运用ASP可将VBscript、javascript等脚本语言嵌入到HTML中,便可快速完成网站的应用程序,无需编译,可在服务器端直接执行。容易编写。
页:
[1]