﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>博客园-装配中的脑袋</title><link>http://www.cnblogs.com/Ninputer/</link><description>用大脑装配程序，再用程序装配大脑</description><language>zh-cn</language><lastBuildDate>Mon, 06 Jul 2009 06:05:10 GMT</lastBuildDate><pubDate>Mon, 06 Jul 2009 06:05:10 GMT</pubDate><ttl>60</ttl><item><title>Silverlight版相机取景器大小比较器</title><link>http://www.cnblogs.com/Ninputer/archive/2009/04/01/ovfcomparer.html</link><dc:creator>装配脑袋</dc:creator><author>装配脑袋</author><pubDate>Wed, 01 Apr 2009 05:50:00 GMT</pubDate><guid>http://www.cnblogs.com/Ninputer/archive/2009/04/01/ovfcomparer.html</guid><wfw:comment>http://www.cnblogs.com/Ninputer/comments/1427205.html</wfw:comment><comments>http://www.cnblogs.com/Ninputer/archive/2009/04/01/ovfcomparer.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnblogs.com/Ninputer/comments/commentRss/1427205.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Ninputer/services/trackbacks/1427205.html</trackback:ping><description><![CDATA[<p>需要Silverlight 2.0，如无法使用请安装Silverlight 2.0。支持Windows和Mac，支持IE、FF、Safari和Chrome等浏览器</p>
<object style="width: 930px; height: 700px" data="data:application/x-oleobject;base64,QfXq3+HzJEysrJnDBxUISgAIAAAeYAAAWEgAAAwAAAB3AGgAaQB0AGUAAAAAAAAAAAAAAGQAAABoAHQAdABwADoALwAvAGYAaQBsAGUAcwAuAGMAbgBiAGwAbwBnAHMALgBjAG8AbQAvAE4AaQBuAHAAdQB0AGUAcgAvAE8AVgBGAEMAbwBtAHAAYQByAGUAcgAuAHgAYQBwAAAAPAAAAAAAAAAmAAAAbwBuAFMAaQBsAHYAZQByAGwAaQBnAGgAdABFAHIAcgBvAHIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAABgAAAAyAC4AMAAuADMAMQAwADAANQAuADAAAAAKAAAAdAByAHUAZQAAAA==" width="69.1%" height="154.31%" type="application/x-silverlight-2">
<param name="source" value="http://files.cnblogs.com/Ninputer/OVFComparer2.xap"            />
<param name="onerror" value="onSilverlightError"            />
<param name="background" value="white"           />
<param name="minRuntimeVersion" value="2.0.31005.0"            />
<param name="autoUpgrade" value="true"            />
<a href="http://go.microsoft.com/fwlink/?LinkID=124807" style="text-decoration: none;">
<img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style: none"       />
</a></object><img src ="http://www.cnblogs.com/Ninputer/aggbug/1427205.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/48002/" target="_blank">竞争日趋激烈 微软欲借 Windows 7 扭转战局</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>.NET 4.0中的泛型协变和反变</title><link>http://www.cnblogs.com/Ninputer/archive/2008/11/22/generic_covariant.html</link><dc:creator>装配脑袋</dc:creator><author>装配脑袋</author><pubDate>Sat, 22 Nov 2008 09:48:00 GMT</pubDate><guid>http://www.cnblogs.com/Ninputer/archive/2008/11/22/generic_covariant.html</guid><wfw:comment>http://www.cnblogs.com/Ninputer/comments/1339058.html</wfw:comment><comments>http://www.cnblogs.com/Ninputer/archive/2008/11/22/generic_covariant.html#Feedback</comments><slash:comments>35</slash:comments><wfw:commentRss>http://www.cnblogs.com/Ninputer/comments/commentRss/1339058.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Ninputer/services/trackbacks/1339058.html</trackback:ping><description><![CDATA[<p style="margin: 0in 0in 10pt"><span style="font-family: 宋体">随</span>Visual Studio 2010 CTP<span style="font-family: 宋体">亮相的</span>C#4<span style="font-family: 宋体">和</span>VB10<span style="font-family: 宋体">，虽然在支持语言新特性方面走了相当不一样的两条路：</span>C#<span style="font-family: 宋体">着重增加后期绑定和与动态语言相容的若干特性，</span>VB10<span style="font-family: 宋体">着重简化语言和提高抽象能力；但是两者都增加了一项功能：泛型类型的协变（</span>covariant<span style="font-family: 宋体">）和反变（</span>contravariant<span style="font-family: 宋体">）。许多人对其了解可能仅限于增加的</span>in/out<span style="font-family: 宋体">关键字，而对其诸多特性有所不知。下面我们就对此进行一些详细的解释，帮助大家正确使用该特性。</span></p>
<h2><span style="color: #3366ff; font-family: 宋体">背景知识：协变和反变</span></h2>
<p style="margin: 0in 0in 10pt"><span style="font-family: 宋体">很多人可能不不能很好地理解这些来自于物理和数学的名词。我们无需去了解他们的数学定义，但是至少应该能分清协变和反变。实际上这个词来源于类型和类型之间的绑定。我们从数组开始理解。数组其实就是一种和具体类型之间发生绑定的类型。数组类型</span>Int32[]<span style="font-family: 宋体">就对应于</span>Int32<span style="font-family: 宋体">这个原本的类型。任何类型</span>T<span style="font-family: 宋体">都有其对应的数组类型</span>T[]<span style="font-family: 宋体">。那么我们的问题就来了，如果两个类型</span>T<span style="font-family: 宋体">和</span>U<span style="font-family: 宋体">之间存在一种安全的隐式转换，那么对应的数组类型</span>T[]<span style="font-family: 宋体">和</span>U[]<span style="font-family: 宋体">之间是否也存在这种转换呢？这就牵扯到了将原本类型上存在的类型转换映射到他们的数组类型上的能力，这种能力就称为&#8220;可变性（</span>Variance<span style="font-family: 宋体">）&#8221;。在</span>.NET<span style="font-family: 宋体">世界中，唯一允许可变性的类型转换就是由继承关系带来的&#8220;<strong>子类引用</strong></span><strong>-&gt;</strong><strong><span style="font-family: 宋体">父类引用</span></strong><span style="font-family: 宋体">&#8221;转换。举个例子，就是</span>String<span style="font-family: 宋体">类型继承自</span>Object<span style="font-family: 宋体">类型，所以任何</span>String<span style="font-family: 宋体">的引用都可以安全地转换为</span>Object<span style="font-family: 宋体">引用。我们发现</span>String[]<span style="font-family: 宋体">数组类型的引用也继承了这种转换能力，它可以转换成</span>Object[]<span style="font-family: 宋体">数组类型的引用，数组<strong>这种与原始类型转换方向相同的可变性就称作协变（</strong></span><strong>covariant</strong><strong><span style="font-family: 宋体">）</span></strong><span style="font-family: 宋体">。</span></p>
<p style="margin: 0in 0in 10pt"><span style="font-family: 宋体">由于数组不支持反变性，我们无法用数组的例子来解释反变性，所以我们现在就来看看泛型接口和泛型委托的可变性。假设有这样两个类型：</span>TSub<span style="font-family: 宋体">是</span>TParent<span style="font-family: 宋体">的子类，显然</span>TSub<span style="font-family: 宋体">型引用是可以安全转换为</span>TParent<span style="font-family: 宋体">型引用的。如果一个泛型接口</span>IFoo&lt;T&gt;<span style="font-family: 宋体">，</span>IFoo&lt;TSub&gt;<span style="font-family: 宋体">可以转换为</span>IFoo&lt;TParent&gt;<span style="font-family: 宋体">的话，我们称这个过程为协变，而且说<strong>这个泛型接口支持对</strong></span><strong>T</strong><strong><span style="font-family: 宋体">的协变</span></strong><span style="font-family: 宋体">。而如果一个泛型接口</span>IBar&lt;T&gt;<span style="font-family: 宋体">，</span>IBar&lt;TParent&gt;<span style="font-family: 宋体">可以转换为</span>T&lt;TSub&gt;<span style="font-family: 宋体">的话，我们称这个过程为<strong>反变（</strong></span><strong>contravariant</strong><strong><span style="font-family: 宋体">）</span></strong><span style="font-family: 宋体">，<strong>而且说这个接口支持对</strong></span><strong>T</strong><strong><span style="font-family: 宋体">的反变</span></strong><span style="font-family: 宋体">。因此很好理解，如果一个可变性和子类到父类转换的方向一样，就称作协变；而如果和子类到父类的转换方向相反，就叫反变性。你记住了吗？</span></p>
<h2><span style="color: #3366ff">.NET 4.0<span style="font-family: 宋体">引入的泛型协变、反变性</span></span></h2>
<p style="margin: 0in 0in 10pt"><span style="font-family: 宋体">刚才我们讲解概念的时候已经用了泛型接口的协变和反变，但在</span>.NET 4.0<span style="font-family: 宋体">之前，无论</span>C#<span style="font-family: 宋体">还是</span>VB<span style="font-family: 宋体">里都不支持泛型的这种可变性。不过它们都支持委托参数类型的协变和反变。由于委托参数类型的可变性理解起来抽象度较高，所以我们这里不准备讨论。已经完全能够理解这些概念的读者自己想必能够自己去理解委托参数类型的可变性。在</span>.NET 4.0<span style="font-family: 宋体">之前为什么不允许</span>IFoo&lt;T&gt;<span style="font-family: 宋体">进行协变或反变呢？因为对接口来讲，</span>T<span style="font-family: 宋体">这个类型参数既可以用于方法参数，也可以用于方法返回值。设想这样的接口</span></p>
<table style="border-right: medium none; border-top: medium none; border-left: medium none; border-bottom: medium none; border-collapse: collapse" cellspacing="0" cellpadding="0" border="1">
    <tr>
            <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: black 1pt solid; padding-left: 5.4pt; padding-bottom: 0in; border-left: black 1pt solid; width: 6.65in; padding-top: 0in; border-bottom: black 1pt solid; background-color: transparent" valign="top" width="638">
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">Interface</span><span style="font-size: 10pt; font-family: Consolas"> IFoo(<span style="color: blue">Of</span> T)</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp; <span style="color: blue">Sub</span> Method1(<span style="color: blue">ByVal</span> param <span style="color: blue">As</span> T)</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp; <span style="color: blue">Function</span> Method2() <span style="color: blue">As</span> T</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">End</span><span style="font-size: 10pt; font-family: Consolas"> <span style="color: blue">Interface</span></span></p>
            </td>
        </tr>
        <tr>
            <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: #f0f0f0; padding-left: 5.4pt; padding-bottom: 0in; border-left: black 1pt solid; width: 6.65in; padding-top: 0in; border-bottom: black 1pt solid; background-color: transparent" valign="top" width="638">
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">interface</span><span style="font-size: 10pt; font-family: Consolas"> <span style="color: #2b91af">IFoo</span>&lt;T&gt;</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">{</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp; <span style="color: blue">void</span> Method1(T param);</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp; T Method2();</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">}</span></p>
            </td>
        </tr>
    </table>
<p style="margin: 0in 0in 10pt"><span style="font-family: 宋体">如果我们允许协变，从</span>IFoo&lt;TSub&gt;<span style="font-family: 宋体">到</span>IFoo&lt;TParent&gt;<span style="font-family: 宋体">转换，那么</span>IFoo.Method1(TSub)<span style="font-family: 宋体">就会变成</span>IFoo.Method1(TParent)<span style="font-family: 宋体">。我们都知道</span>TParent<span style="font-family: 宋体">是不能安全转换成</span>TSub<span style="font-family: 宋体">的，所以</span>Method1<span style="font-family: 宋体">这个方法就会变得不安全。同样，如果我们允许反变</span>IFoo&lt;TParent&gt;<span style="font-family: 宋体">到</span>IFoo&lt;TSub&gt;<span style="font-family: 宋体">，则</span>TParent IFoo.Method2()<span style="font-family: 宋体">方法就会变成</span>TSub IFoo.Method2()<span style="font-family: 宋体">，原本返回的</span>TParent<span style="font-family: 宋体">引用未必能够转换成</span>TSub<span style="font-family: 宋体">的引用，</span>Method2<span style="font-family: 宋体">的调用将是不安全的。有此可见，在没有额外机制的限制下，接口进行协变或反变都是类型不安全的。</span>.NET 4.0<span style="font-family: 宋体">改进了什么呢？它允许在类型参数的声明时增加一个额外的描述，以确定这个类型参数的使用范围。我们看到，如果一个类型参数仅仅能用于函数的返回值，那么这个类型参数就对协变相容。而相反，一个类型参数如果仅能用于方法参数，那么这个类型参数就对反变相容。如下所示：</span></p>
<table style="border-right: medium none; border-top: medium none; border-left: medium none; border-bottom: medium none; border-collapse: collapse" cellspacing="0" cellpadding="0" border="1">
    <tr>
            <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: black 1pt solid; padding-left: 5.4pt; padding-bottom: 0in; border-left: black 1pt solid; width: 6.65in; padding-top: 0in; border-bottom: black 1pt solid; background-color: transparent" valign="top" width="638">
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">Interface</span><span style="font-size: 10pt; font-family: Consolas"> ICo(<span style="color: blue">Of</span> <span style="color: blue">Out</span> T)</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp; <span style="color: blue">Function</span> Method() <span style="color: blue">As</span> T</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">End</span><span style="font-size: 10pt; font-family: Consolas"> <span style="color: blue">Interface</span></span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal">&nbsp;</p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">Interface</span><span style="font-size: 10pt; font-family: Consolas"> IContra(<span style="color: blue">Of</span> <span style="color: blue">In</span> T)</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp; <span style="color: blue">Sub</span> Method(<span style="color: blue">ByVal</span> param <span style="color: blue">As</span> T)</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">End</span><span style="font-size: 10pt; font-family: Consolas"> <span style="color: blue">Interface</span></span></p>
            </td>
        </tr>
        <tr>
            <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: #f0f0f0; padding-left: 5.4pt; padding-bottom: 0in; border-left: black 1pt solid; width: 6.65in; padding-top: 0in; border-bottom: black 1pt solid; background-color: transparent" valign="top" width="638">
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">interface</span><span style="font-size: 10pt; font-family: Consolas"> <span style="color: #2b91af">ICo</span>&lt;<span style="color: blue">out</span> T&gt;</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">{</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp; T Method();</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">}</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal">&nbsp;</p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">interface</span><span style="font-size: 10pt; font-family: Consolas"> <span style="color: #2b91af">IContra</span>&lt;<span style="color: blue">in</span> T&gt;</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">{</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp; <span style="color: blue">void</span> Method(T param);</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">}</span></p>
            </td>
        </tr>
    </table>
<p style="margin: 0in 0in 10pt"><span style="font-family: 宋体">可以看到</span>C#4<span style="font-family: 宋体">和</span>VB10<span style="font-family: 宋体">都提供了大同小异的语法，用</span>Out<span style="font-family: 宋体">来描述仅能作为返回值的类型参数，用</span>In<span style="font-family: 宋体">来描述仅能作为方法参数的类型参数。一个接口可以带多个类型参数，这些参数可以既有</span>In<span style="font-family: 宋体">也有</span>Out<span style="font-family: 宋体">，因此我们不能简单地说一个接口支持协变还是反变，只能说一个接口对某个具体的类型参数支持协变或反变。比如若有</span>IBar&lt;in T1, out T2&gt;<span style="font-family: 宋体">这样的接口，则它对</span>T1<span style="font-family: 宋体">支持反变而对</span>T2<span style="font-family: 宋体">支持协变。举个例子来说，</span>IBar&lt;object, string&gt;<span style="font-family: 宋体">能够转换成</span>IBar&lt;string, object&gt;<span style="font-family: 宋体">，这里既有协变又有反变。</span></p>
<p style="margin: 0in 0in 10pt"><span style="font-family: 宋体">在</span>.NET Framework<span style="font-family: 宋体">中，许多接口都仅仅将类型参数用于参数或返回值。为了使用方便，在</span>.NET Framework 4.0<span style="font-family: 宋体">里这些接口将重新声明为允许协变或反变的版本。例如</span>IComparable&lt;T&gt;<span style="font-family: 宋体">就可以重新声明成</span>IComparable&lt;in T&gt;<span style="font-family: 宋体">，而</span>IEnumerable&lt;T&gt;<span style="font-family: 宋体">则可以重新声明为</span>IEnumerable&lt;out T&gt;<span style="font-family: 宋体">。不过某些接口</span>IList&lt;T&gt;<span style="font-family: 宋体">是不能声明为</span>in<span style="font-family: 宋体">或</span>out<span style="font-family: 宋体">的，因此也就无法支持协变或反变。</span></p>
<p style="margin: 0in 0in 10pt"><span style="font-family: 宋体">下面提起几个泛型协变和反变容易忽略的注意事项：</span></p>
<p style="margin: 0in 0in 0pt 0.5in; text-indent: -0.25in">1.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">仅有泛型接口和泛型委托支持对类型参数的可变性，泛型类或泛型方法是不支持的。</span></p>
<p style="margin: 0in 0in 0pt 0.5in; text-indent: -0.25in">2.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">值类型不参与协变或反变，</span>IFoo&lt;int&gt;<span style="font-family: 宋体">永远无法变成</span>IFoo&lt;object&gt;<span style="font-family: 宋体">，不管有无声明</span>out<span style="font-family: 宋体">。因为</span>.NET<span style="font-family: 宋体">泛型，每个值类型会生成专属的封闭构造类型，与引用类型版本不兼容。</span></p>
<p style="margin: 0in 0in 10pt 0.5in; text-indent: -0.25in">3.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">声明属性时要注意，可读写的属性会将类型同时用于参数和返回值。因此只有只读属性才允许使用</span>out<span style="font-family: 宋体">类型参数，只写属性能够使用</span>in<span style="font-family: 宋体">参数。</span></p>
<h2><span style="color: #3366ff; font-family: 宋体">协变和反变的相互作用</span></h2>
<p style="margin: 0in 0in 10pt"><span style="font-family: 宋体">这是一个相当有趣的话题，我们先来看一个例子：</span></p>
<table style="border-right: medium none; border-top: medium none; border-left: medium none; border-bottom: medium none; border-collapse: collapse" cellspacing="0" cellpadding="0" border="1">
    <tr>
            <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: black 1pt solid; padding-left: 5.4pt; padding-bottom: 0in; border-left: black 1pt solid; width: 6.65in; padding-top: 0in; border-bottom: black 1pt solid; background-color: transparent" valign="top" width="638">
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">Interface</span><span style="font-size: 10pt; font-family: Consolas"> IFoo(<span style="color: blue">Of</span> <span style="color: blue">In</span> T)</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal">&nbsp;</p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">End</span><span style="font-size: 10pt; font-family: Consolas"> <span style="color: blue">Interface</span></span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal">&nbsp;</p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">Interface</span><span style="font-size: 10pt; font-family: Consolas"> IBar(<span style="color: blue">Of</span> <span style="color: blue">In</span> T)</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp; <span style="color: blue">Sub</span> Test(<span style="color: blue">ByVal</span> foo <span style="color: blue">As</span> IFoo(<span style="color: blue">Of</span> T)) <span style="color: green">'</span></span><span style="font-size: 10pt; color: green; font-family: 宋体">对吗？</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">End</span><span style="font-size: 10pt; font-family: Consolas"> <span style="color: blue">Interface</span></span></p>
            </td>
        </tr>
        <tr>
            <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: #f0f0f0; padding-left: 5.4pt; padding-bottom: 0in; border-left: black 1pt solid; width: 6.65in; padding-top: 0in; border-bottom: black 1pt solid; background-color: transparent" valign="top" width="638">
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">interface</span><span style="font-size: 10pt; font-family: Consolas"> <span style="color: #2b91af">IFoo</span>&lt;<span style="color: blue">in</span> T&gt;</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">{</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal">&nbsp;</p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">}</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal">&nbsp;</p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">interface</span><span style="font-size: 10pt; font-family: Consolas"> <span style="color: #2b91af">IBar</span>&lt;<span style="color: blue">in</span> T&gt;</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">{</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp; <span style="color: blue">void</span> Test(<span style="color: #2b91af">IFoo</span>&lt;T&gt; foo); <span style="color: green">//</span></span><span style="font-size: 10pt; color: green; font-family: 宋体">对吗？</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">}</span></p>
            </td>
        </tr>
    </table>
<p style="margin: 0in 0in 10pt"><span style="font-family: 宋体">你能看出上述代码有什么问题吗？我声明了</span>in T<span style="font-family: 宋体">，然后将他用于方法的参数了，一切正常。但出乎你意料的是，这段代码是无法编译通过的！反而是这样的代码通过了编译：</span></p>
<table style="border-right: medium none; border-top: medium none; border-left: medium none; border-bottom: medium none; border-collapse: collapse" cellspacing="0" cellpadding="0" border="1">
    <tr>
            <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: black 1pt solid; padding-left: 5.4pt; padding-bottom: 0in; border-left: black 1pt solid; width: 6.65in; padding-top: 0in; border-bottom: black 1pt solid; background-color: transparent" valign="top" width="638">
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">Interface</span><span style="font-size: 10pt; font-family: Consolas"> IFoo(<span style="color: blue">Of</span> <span style="color: blue">In</span> T)</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal">&nbsp;</p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">End</span><span style="font-size: 10pt; font-family: Consolas"> <span style="color: blue">Interface</span></span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal">&nbsp;</p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">Interface</span><span style="font-size: 10pt; font-family: Consolas"> IBar(<span style="color: blue">Of</span> <span style="color: blue">Out</span> T)</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp; <span style="color: blue">Sub</span> Test(<span style="color: blue">ByVal</span> foo <span style="color: blue">As</span> IFoo(<span style="color: blue">Of</span> T)) </span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">End</span><span style="font-size: 10pt; font-family: Consolas"> <span style="color: blue">Interface</span></span></p>
            </td>
        </tr>
        <tr>
            <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: #f0f0f0; padding-left: 5.4pt; padding-bottom: 0in; border-left: black 1pt solid; width: 6.65in; padding-top: 0in; border-bottom: black 1pt solid; background-color: transparent" valign="top" width="638">
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">interface</span><span style="font-size: 10pt; font-family: Consolas"> <span style="color: #2b91af">IFoo</span>&lt;<span style="color: blue">in</span> T&gt;</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">{</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal">&nbsp;</p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">}</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal">&nbsp;</p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">interface</span><span style="font-size: 10pt; font-family: Consolas"> <span style="color: #2b91af">IBar</span>&lt;<span style="color: blue">out</span> T&gt;</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">{</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp; <span style="color: blue">void</span> Test(<span style="color: #2b91af">IFoo</span>&lt;T&gt; foo); </span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">}</span></p>
            </td>
        </tr>
    </table>
<p style="margin: 0in 0in 10pt"><span style="font-family: 宋体">什么？明明是</span>out<span style="font-family: 宋体">参数，我们却要将其用于方法的参数才合法？初看起来的确会有一些惊奇。我们需要费一些周折来理解这个问题。现在我们考虑</span>IBar&lt;string&gt;<span style="font-family: 宋体">，它应该能够协变成</span>IBar&lt;object&gt;<span style="font-family: 宋体">，因为</span>string<span style="font-family: 宋体">是</span>object<span style="font-family: 宋体">的子类。因此</span>IBar.Test(IFoo&lt;string&gt;)<span style="font-family: 宋体">也就协变成了</span>IBar.Test(IFoo&lt;object&gt;)<span style="font-family: 宋体">。当我们调用这个协变后方法时，将会传入一个</span>IFoo&lt;object&gt;<span style="font-family: 宋体">作为参数。想一想，这个方法是从</span>IBar.Test(IFoo&lt;string&gt;)<span style="font-family: 宋体">协变来的，所以参数</span>IFoo&lt;object&gt;<span style="font-family: 宋体">必须能够变成</span>IFoo&lt;string&gt;<span style="font-family: 宋体">才能满足原函数的需要。这里对</span>IFoo&lt;object&gt;<span style="font-family: 宋体">的要求是它能够<strong>反变</strong>成</span>IFoo&lt;string&gt;<span style="font-family: 宋体">！而不是协变。也就是说，<strong>如果一个接口需要对</strong></span><strong>T</strong><strong><span style="font-family: 宋体">协变，那么这个接口所有方法的参数类型必须支持对</span>T</strong><strong><span style="font-family: 宋体">的反变</span></strong><span style="font-family: 宋体">。同理我们也可以看出，<strong>如果接口要支持对</strong></span><strong>T</strong><strong><span style="font-family: 宋体">反变，那么接口中方法的参数类型都必须支持对</span>T</strong><strong><span style="font-family: 宋体">协变</span></strong><span style="font-family: 宋体">才行。<strong>这就是方法参数的协变</strong></span><strong>-</strong><strong><span style="font-family: 宋体">反变互换原则</span></strong><span style="font-family: 宋体">。所以，我们并不能简单地说</span>out<span style="font-family: 宋体">参数只能用于返回值，它确实只能直接用于声明返回值类型，但是只要一个支持反变的类型协助，</span>out<span style="font-family: 宋体">类型参数就也可以用于参数类型！换句话说，</span>in<span style="font-family: 宋体">参数除了直接声明方法参数之外，也仅能借助支持协变的类型才能用于方法参数，仅支持对</span>T<span style="font-family: 宋体">反变的类型作为方法参数也是不允许的。要想深刻理解这一概念，第一次看可能会有点绕，建议有条件的情况下多进行一些实验。</span></p>
<p style="margin: 0in 0in 10pt"><span style="font-family: 宋体">刚才提到了方法参数上协变和反变的相互影响。那么方法的返回值会不会有同样的问题呢？我们看如下代码：</span></p>
<table style="border-right: medium none; border-top: medium none; border-left: medium none; border-bottom: medium none; border-collapse: collapse" cellspacing="0" cellpadding="0" border="1">
    <tr>
            <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: black 1pt solid; padding-left: 5.4pt; padding-bottom: 0in; border-left: black 1pt solid; width: 6.65in; padding-top: 0in; border-bottom: black 1pt solid; background-color: transparent" valign="top" width="638">
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">Interface</span><span style="font-size: 10pt; font-family: Consolas"> IFooCo(<span style="color: blue">Of</span> <span style="color: blue">Out</span> T)</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal">&nbsp;</p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">End</span><span style="font-size: 10pt; font-family: Consolas"> <span style="color: blue">Interface</span></span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal">&nbsp;</p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">Interface</span><span style="font-size: 10pt; font-family: Consolas"> IFooContra(<span style="color: blue">Of</span> <span style="color: blue">In</span> T)</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal">&nbsp;</p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">End</span><span style="font-size: 10pt; font-family: Consolas"> <span style="color: blue">Interface</span></span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal">&nbsp;</p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">Interface</span><span style="font-size: 10pt; font-family: Consolas"> IBar(<span style="color: blue">Of</span> <span style="color: blue">Out</span> T1, <span style="color: blue">In</span> T2)</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp; <span style="color: blue">Function</span> Test1() <span style="color: blue">As</span> IFooCo(<span style="color: blue">Of</span> T1)</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp; <span style="color: blue">Function</span> Test2() <span style="color: blue">As</span> IFooContra(<span style="color: blue">Of</span> T2)</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">End</span><span style="font-size: 10pt; font-family: Consolas"> <span style="color: blue">Interface</span></span></p>
            </td>
        </tr>
        <tr>
            <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: #f0f0f0; padding-left: 5.4pt; padding-bottom: 0in; border-left: black 1pt solid; width: 6.65in; padding-top: 0in; border-bottom: black 1pt solid; background-color: transparent" valign="top" width="638">
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">interface</span><span style="font-size: 10pt; font-family: Consolas"> <span style="color: #2b91af">IFooCo</span>&lt;<span style="color: blue">out</span> T&gt;</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">{</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">}</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal">&nbsp;</p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">interface</span><span style="font-size: 10pt; font-family: Consolas"> <span style="color: #2b91af">IFooContra</span>&lt;<span style="color: blue">in</span> T&gt;</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">{</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">}</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal">&nbsp;</p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">interface</span><span style="font-size: 10pt; font-family: Consolas"> <span style="color: #2b91af">IBar</span>&lt;<span style="color: blue">out</span> T1, <span style="color: blue">in</span> T2&gt;</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">{</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp; <span style="color: #2b91af">IFooCo</span>&lt;T1&gt; Test1();</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp; <span style="color: #2b91af">IFooContra</span>&lt;T2&gt; Test2();</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">}</span></p>
            </td>
        </tr>
    </table>
<p style="margin: 0in 0in 10pt"><span style="font-family: 宋体">我们看到和刚刚正好相反，<strong>如果一个接口需要对</strong></span><strong>T</strong><strong><span style="font-family: 宋体">进行协变或反变，那么这个接口所有方法的返回值类型必须支持对</span>T</strong><strong><span style="font-family: 宋体">同样方向的协变或反变</span></strong><span style="font-family: 宋体">。<strong>这就是方法返回值的协变</strong></span><strong>-</strong><strong><span style="font-family: 宋体">反变一致原则</span></strong><span style="font-family: 宋体">。也就是说，即使</span>in<span style="font-family: 宋体">参数也可以用于方法的返回值类型，只要借助一个可以反变的类型作为桥梁即可。如果对这个过程还不是特别清楚，建议也是写一些代码来进行实验。至此我们发现协变和反变有许多有趣的特性，以至于在代码里</span>in<span style="font-family: 宋体">和</span>out<span style="font-family: 宋体">都不像他们字面意思那么好理解。当你看到</span>in<span style="font-family: 宋体">参数出现在返回值类型，</span>out<span style="font-family: 宋体">参数出现在参数类型时，千万别晕倒，用本文的知识即可破解其中奥妙。</span></p>
<h2><span style="color: #3366ff; font-family: 宋体">总结</span></h2>
<p style="margin: 0in 0in 10pt"><span style="font-family: 宋体">经过本文的讲解，大家应该已经初步了解的协变和反变的含义，能够分清协变、反变的过程。我们还讨论了</span>.NET 4.0<span style="font-family: 宋体">支持泛型接口、委托的协变和反变的新功能和新语法。最后我们还套了论的协变、反变与函数参数、返回值的相互作用原理，以及由此产生的奇妙写法。我希望大家看了我的文章后，能够将这些知识用于泛型程序设计当中，正确运用</span>.NET 4.0<span style="font-family: 宋体">的新增功能。祝大家使用愉快！</span></p>
<img src ="http://www.cnblogs.com/Ninputer/aggbug/1339058.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/48001/" target="_blank">上海电信计划2012年80%用户实现100M带宽</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>关于Visual Basic 10.0</title><link>http://www.cnblogs.com/Ninputer/archive/2008/11/03/vb10firstlook.html</link><dc:creator>装配脑袋</dc:creator><author>装配脑袋</author><pubDate>Mon, 03 Nov 2008 08:10:00 GMT</pubDate><guid>http://www.cnblogs.com/Ninputer/archive/2008/11/03/vb10firstlook.html</guid><wfw:comment>http://www.cnblogs.com/Ninputer/comments/1325602.html</wfw:comment><comments>http://www.cnblogs.com/Ninputer/archive/2008/11/03/vb10firstlook.html#Feedback</comments><slash:comments>20</slash:comments><wfw:commentRss>http://www.cnblogs.com/Ninputer/comments/commentRss/1325602.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Ninputer/services/trackbacks/1325602.html</trackback:ping><description><![CDATA[<p style="margin: 0in 0in 10pt"><span style="font-family: 宋体">随着</span>VS2010<span style="font-family: 宋体">早期</span>CTP<span style="font-family: 宋体">的放出，大家对下一代开发系统的期待热情又一次掀起了。除了已经开始被大家尝鲜的</span>C#4<span style="font-family: 宋体">以外，</span>Visual Basic<span style="font-family: 宋体">也进化成了</span>10.0<span style="font-family: 宋体">。不过据我观察，</span>VB10<span style="font-family: 宋体">的改变还没有</span>C#4<span style="font-family: 宋体">那么明朗，我们目前的确可以看到一些语法上的变化，然而似乎</span>VB10<span style="font-family: 宋体">并未真正接近完工的地步，还有很多特性有待继续开发。大家也许还记得</span>VB9<span style="font-family: 宋体">引入的令人眼前一亮的</span>XML<span style="font-family: 宋体">集成语法，使得</span>VB<span style="font-family: 宋体">拥有了业界最为紧密的</span>XML<span style="font-family: 宋体">集成。但</span>VB<span style="font-family: 宋体">需要编译才能使用，这一点阻碍了</span>VB<span style="font-family: 宋体">强大的</span>XML<span style="font-family: 宋体">处理能力和动态能力，如果</span>VB<span style="font-family: 宋体">变成一个完全动态的编程语言，包括脚本化运行的能力，那么</span>VB<span style="font-family: 宋体">使用方便的特点将再一次发挥出来。但是</span>VS2010 CTP<span style="font-family: 宋体">中尚未看到基于新</span>DLR<span style="font-family: 宋体">的</span>VB<span style="font-family: 宋体">编译器。我们能看到的仍然是一个静态编译的</span>VB10<span style="font-family: 宋体">。所以我这次主要介绍一下</span>VB<span style="font-family: 宋体">语法方面的改进，更多改进等到</span>VS2010<span style="font-family: 宋体">来临之际自然会知晓。</span></p>
<p style="margin: 0in 0in 10pt 0.5in; text-indent: -0.25in">1.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">隐式续行符</span></p>
<p style="margin: 0in 0in 10pt"><span style="font-family: 宋体">用过</span>VB<span style="font-family: 宋体">的人都知道</span>VB<span style="font-family: 宋体">的语句是写成一行一行的，无需分号隔离。一般情况下语句只能写成一行，不能换行。而从</span>VB5.0<span style="font-family: 宋体">开始，如果觉得语句写成一行太长，可以加入续行符（</span>line continuation<span style="font-family: 宋体">）来换行。比如说：</span></p>
<table style="border-right: medium none; border-top: medium none; border-left: medium none; border-bottom: medium none; border-collapse: collapse" cellspacing="0" cellpadding="0" border="1">
    <tr>
            <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: black 1pt solid; padding-left: 5.4pt; padding-bottom: 0in; border-left: black 1pt solid; width: 6.65in; padding-top: 0in; border-bottom: black 1pt solid; background-color: transparent" valign="top" width="638">
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&lt;HideModuleName()&gt; _</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">Module</span><span style="font-size: 10pt; font-family: Consolas"> Module1</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal">&nbsp;</p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp; &lt;STAThread()&gt; _</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp; <span style="color: blue">Sub</span> Main()</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue">Dim</span> message = <span style="color: #a31515">"Your directory is"</span> &amp; _</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Environment.CurrentDirectory()</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal">&nbsp;</p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue">Dim</span> l <span style="color: blue">As</span> <span style="color: blue">New</span> List(<span style="color: blue">Of</span> <span style="color: blue">Integer</span>)</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue">Dim</span> r = <span style="color: blue">From</span> item <span style="color: blue">In</span> l _</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue">Where</span> item &gt; 0 <span style="color: blue">AndAlso</span> item &lt; 100 _</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue">Select</span> Number = item.ToString()</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp; <span style="color: blue">End</span> <span style="color: blue">Sub</span></span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal">&nbsp;</p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp; <span style="color: blue">Function</span> Foo(<span style="color: blue">ByVal</span> x <span style="color: blue">As</span> <span style="color: blue">Integer</span>, _</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue">ByVal</span> y <span style="color: blue">As</span> <span style="color: blue">String</span>, _</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue">ByVal</span> z <span style="color: blue">As</span> <span style="color: blue">Double</span>) <span style="color: blue">As</span> <span style="color: blue">Single</span></span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp; <span style="color: blue">End</span> <span style="color: blue">Function</span></span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">End</span><span style="font-size: 10pt; font-family: Consolas"> <span style="color: blue">Module</span></span></p>
            </td>
        </tr>
    </table>
<p style="margin: 0in 0in 10pt"><span style="font-family: 宋体">我们可以看到这段代码中多处出现了续行符（就是一个空格加一个下划线）。无论是</span>Attribute<span style="font-family: 宋体">应用语法，还是表达式、</span>Linq<span style="font-family: 宋体">表达式或函数签名，都必须用续行符来换行。</span></p>
<p style="margin: 0in 0in 10pt"><span style="font-family: 宋体">首先我们说换行并非必须，而仅仅是为了美观。像</span>Linq<span style="font-family: 宋体">这样的语法出现之后，换行书写就成了很多人的迫切需要。因此</span>VB10<span style="font-family: 宋体">改进了语法，引入了隐式换行符的概念。当</span>VB<span style="font-family: 宋体">能够判断一行语法未完的上下文，就会自动将紧接的一行视为续行，而无需显示加入续行符。这样一来在常见的场合，你就可以任意换行，充分发扬</span>Basic<span style="font-family: 宋体">语言的自由风格了：</span></p>
<table style="border-right: medium none; border-top: medium none; border-left: medium none; border-bottom: medium none; border-collapse: collapse" cellspacing="0" cellpadding="0" border="1">
    <tr>
            <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: black 1pt solid; padding-left: 5.4pt; padding-bottom: 0in; border-left: black 1pt solid; width: 6.65in; padding-top: 0in; border-bottom: black 1pt solid; background-color: transparent" valign="top" width="638">
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&lt;HideModuleName()&gt;</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">Module</span><span style="font-size: 10pt; font-family: Consolas"> Module1</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal">&nbsp;</p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp; &lt;STAThread()&gt;</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp; <span style="color: blue">Sub</span> Main()</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue">Dim</span> message = <span style="color: #a31515">"Your directory is"</span> &amp;</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Environment.CurrentDirectory()</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal">&nbsp;</p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue">Dim</span> l <span style="color: blue">As</span> <span style="color: blue">New</span> List(<span style="color: blue">Of</span> <span style="color: blue">Integer</span>)</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue">Dim</span> r = <span style="color: blue">From</span> item <span style="color: blue">In</span> l</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue">Where</span> item &gt; 0 <span style="color: blue">AndAlso</span> item &lt; 100</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue">Select</span> Number = item.ToString()</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp; <span style="color: blue">End</span> <span style="color: blue">Sub</span></span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal">&nbsp;</p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp; <span style="color: blue">Function</span> Foo(<span style="color: blue">ByVal</span> x <span style="color: blue">As</span> <span style="color: blue">Integer</span>,</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue">ByVal</span> y <span style="color: blue">As</span> <span style="color: blue">String</span>,</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue">ByVal</span> z <span style="color: blue">As</span> <span style="color: blue">Double</span>) <span style="color: blue">As</span> <span style="color: blue">Single</span></span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp; <span style="color: blue">End</span> <span style="color: blue">Function</span></span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">End</span><span style="font-size: 10pt; font-family: Consolas"> <span style="color: blue">Module</span></span></p>
            </td>
        </tr>
    </table>
<p style="margin: 0in 0in 10pt"><span style="font-family: 宋体">这样一来清爽多了。不过隐式续行符和显式续行符一样，有个小小的缺陷，就是不能在后面插入注释。据说这是</span>VB IDE<span style="font-family: 宋体">团队过分依赖于此特性，以至于超多历史代码无法一一改变造成的&#8230;&#8230;</span></p>
<p style="margin: 0in 0in 10pt 0.5in; text-indent: -0.25in">2.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">多行</span>Lambda<span style="font-family: 宋体">表达式和方法型</span>Lambda<span style="font-family: 宋体">表达式</span></p>
<p style="margin: 0in 0in 10pt">VB2008<span style="font-family: 宋体">为了支持</span>Linq<span style="font-family: 宋体">已经引入了</span>Lambda<span style="font-family: 宋体">表达式的概念。但</span>VB2008<span style="font-family: 宋体">的</span>Lambda<span style="font-family: 宋体">表达式有局限性，只能是函数形态（必须有返回值），同时最多只能含有一个表达式，所以无法加入多行语句。虽然函数式编程仅支持一行语句也可编写，但若能支持多行语句就能扩大与</span>VB<span style="font-family: 宋体">传统语法的结合能力。比如说可以用在</span>PLinq<span style="font-family: 宋体">等场合。语法非常简单，就如同是将</span>Sub<span style="font-family: 宋体">和</span>Function<span style="font-family: 宋体">写在了方法体内部一样：</span></p>
<table style="border-right: medium none; border-top: medium none; border-left: medium none; border-bottom: medium none; border-collapse: collapse" cellspacing="0" cellpadding="0" border="1">
    <tr>
            <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: black 1pt solid; padding-left: 5.4pt; padding-bottom: 0in; border-left: black 1pt solid; width: 6.65in; padding-top: 0in; border-bottom: black 1pt solid; background-color: transparent" valign="top" width="638">
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">Dim</span><span style="font-size: 10pt; font-family: Consolas"> f = <span style="color: blue">Function</span>(x) x + 1 <span style="color: green">'</span></span><span style="font-size: 10pt; color: green; font-family: 宋体">函数形态</span><span style="font-size: 10pt; color: green; font-family: Consolas">Lambda</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">Dim</span><span style="font-size: 10pt; font-family: Consolas"> g = <span style="color: blue">Sub</span>(x) Console.WriteLine(x) <span style="color: green">'</span></span><span style="font-size: 10pt; color: green; font-family: 宋体">方法形态</span><span style="font-size: 10pt; color: green; font-family: Consolas">Lambda</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">Dim</span><span style="font-size: 10pt; font-family: Consolas"> h = <span style="color: blue">Function</span>(x, y) <span style="color: green">'</span></span><span style="font-size: 10pt; color: green; font-family: 宋体">多行语句函数</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue">Dim</span> z = x`+ y</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue">Return</span> 2 * Math.Squr(Z)</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue">End</span> <span style="color: blue">Function</span></span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal">&nbsp;</p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">Dim</span><span style="font-size: 10pt; font-family: Consolas"> i = <span style="color: blue">Sub</span>() <span style="color: green">'</span></span><span style="font-size: 10pt; color: green; font-family: 宋体">多行语句子程序</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; f(1)</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g(2)</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; h(3, 4)</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue">End</span> <span style="color: blue">Sub</span></span></p>
            </td>
        </tr>
    </table>
<p style="margin: 0in 0in 10pt"><span style="font-family: 宋体">多行</span>Lambda<span style="font-family: 宋体">和语句型</span>Lambda<span style="font-family: 宋体">都可以捕获局部变量，完成函数式的诸多算法。他们同样也基于匿名委托工作。有了此工具，就可以更有效地在</span>VB<span style="font-family: 宋体">中进行函数式风格的编程了。</span></p>
<p style="margin: 0in 0in 10pt 0.5in; text-indent: -0.25in">3.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">数组、集合和字典的初始化语句。</span></p>
<p style="margin: 0in 0in 10pt"><span style="font-family: 宋体">这个新特性是</span>VB9<span style="font-family: 宋体">日程过于紧迫而被砍掉的特性，其实和</span>C#<span style="font-family: 宋体">的类似功能是一样的。首先，</span>VB10<span style="font-family: 宋体">引入了一个纯粹的数组字面量。无需任何修饰，下列语法就表示一个强类型数组：</span></p>
<table style="border-right: medium none; border-top: medium none; border-left: medium none; border-bottom: medium none; border-collapse: collapse" cellspacing="0" cellpadding="0" border="1">
    <tr>
            <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: black 1pt solid; padding-left: 5.4pt; padding-bottom: 0in; border-left: black 1pt solid; width: 6.65in; padding-top: 0in; border-bottom: black 1pt solid; background-color: transparent" valign="top" width="638">
            <p style="margin: 0in 0in 0pt; line-height: normal">{1, 2, 3, 4}</p>
            </td>
        </tr>
    </table>
<p style="margin: 0in 0in 10pt"><span style="font-family: 宋体">编译器会自动推测它是</span>Integer<span style="font-family: 宋体">类型的数组。这个表达式不仅仅可以用于赋值，还可以直接出现在需要数组的上下文中。这是个很好的特性，基于一些</span>Linq<span style="font-family: 宋体">操作，</span>VB<span style="font-family: 宋体">也可以像函数式语言操作&#8220;表&#8221;一样，在数组上进行一些眼花缭乱的算法了。同时，</span>List(Of T)<span style="font-family: 宋体">和</span>Dictionary(Of TKey, TValue)<span style="font-family: 宋体">类型也可以用类似的表达式初始化。暂定关键字为</span>From<span style="font-family: 宋体">：</span></p>
<table style="border-right: medium none; border-top: medium none; border-left: medium none; border-bottom: medium none; border-collapse: collapse" cellspacing="0" cellpadding="0" border="1">
    <tr>
            <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: black 1pt solid; padding-left: 5.4pt; padding-bottom: 0in; border-left: black 1pt solid; width: 6.65in; padding-top: 0in; border-bottom: black 1pt solid; background-color: transparent" valign="top" width="638">
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">Dim</span><span style="font-size: 10pt; font-family: Consolas"> l <span style="color: blue">As</span> <span style="color: blue">New</span> List(<span style="color: blue">Of</span> <span style="color: blue">Integer</span>) <span style="color: blue">From</span> {1, 2, 3, 4}</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">Dim</span><span style="font-size: 10pt; font-family: Consolas"> d <span style="color: blue">As</span> <span style="color: blue">New</span> Dictionary(<span style="color: blue">Of</span> <span style="color: blue">String</span>, <span style="color: blue">Double</span>) <span style="color: blue">From</span> {{<span style="color: #a31515">"A"</span>, 1}, {<span style="color: #a31515">"B"</span>, 2}}</span></p>
            </td>
        </tr>
    </table>
<p style="margin: 0in 0in 10pt"><span style="font-family: 宋体">其实我个人感觉字典的初始化语法应该像</span>JSON<span style="font-family: 宋体">语法那样才好。。。</span></p>
<p style="margin: 0in 0in 10pt 0.5in; text-indent: -0.25in">4.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">泛型接口和泛型委托的协变、反变性</span></p>
<p style="margin: 0in 0in 10pt"><span style="font-family: 宋体">我们都知道</span>.NET<span style="font-family: 宋体">泛型是不允许任何形式的协变或反变的。也就是说</span>Foo(Of T)<span style="font-family: 宋体">是不可能转成</span>Foo(Of U)<span style="font-family: 宋体">的，不管</span>T<span style="font-family: 宋体">和</span>U<span style="font-family: 宋体">之间有什么样的关系。用过</span>Java<span style="font-family: 宋体">泛型的人可能会对此表示疑问。但其实仔细一想不难发现，泛型参数</span>T<span style="font-family: 宋体">在这个类型中如何被使用我们是不能加以约束的。因此</span>T<span style="font-family: 宋体">既可能出现在成员函数的参数上，也可能出现在返回值上。因此允许协变必然会导致某种类型不安全的现象发生。现在</span>CLR<span style="font-family: 宋体">增加了一种新的描述泛型类型参数的方法，可以限定类型参数只能用于方法的参数或返回值。这样就使得安全的协变成为可能。</span>VB10<span style="font-family: 宋体">为此提供了两种语法（仅能用于声明泛型接口和泛型委托，不能用于泛型类或泛型方法）：</span></p>
<table style="border-right: medium none; border-top: medium none; border-left: medium none; border-bottom: medium none; border-collapse: collapse" cellspacing="0" cellpadding="0" border="1">
    <tr>
            <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: black 1pt solid; padding-left: 5.4pt; padding-bottom: 0in; border-left: black 1pt solid; width: 6.65in; padding-top: 0in; border-bottom: black 1pt solid; background-color: transparent" valign="top" width="638">
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">Interface</span><span style="font-size: 10pt; font-family: Consolas"> IFoo(<span style="color: blue">Of</span> <span style="color: blue">In</span> T)</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp; <span style="color: blue">Sub</span> Foo(<span style="color: blue">ByVal</span> x <span style="color: blue">As</span> T)</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">End</span><span style="font-size: 10pt; font-family: Consolas"> <span style="color: blue">Interface</span></span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal">&nbsp;</p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">Interface</span><span style="font-size: 10pt; font-family: Consolas"> IBar(<span style="color: blue">Of</span> <span style="color: blue">Out</span> T)</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; font-family: Consolas">&nbsp;&nbsp;&nbsp; <span style="color: blue">Function</span> Bar() <span style="color: blue">As</span> T</span></p>
            <p style="margin: 0in 0in 0pt; line-height: normal"><span style="font-size: 10pt; color: blue; font-family: Consolas">End</span><span style="font-size: 10pt; font-family: Consolas"> <span style="color: blue">Interface</span></span></p>
            </td>
        </tr>
    </table>
<p style="margin: 0in 0in 10pt"><span style="font-family: 宋体">其中被</span>In<span style="font-family: 宋体">修饰的泛型类型参数仅能在接口或委托中用于函数的参数类型，而被</span>Out<span style="font-family: 宋体">修饰的泛型类型参数则只能用于返回值类型。</span></p>
<p style="margin: 0in 0in 10pt"><span style="font-family: 宋体">加上这样的修饰之后，该接口就允许某些条件下的协变或反变了。首先，</span>IFoo(Of In T)<span style="font-family: 宋体">将可以<strong>反变</strong>成</span>IFoo(Of In U)<span style="font-family: 宋体">，当且仅当</span>U<span style="font-family: 宋体">继承自</span>T<span style="font-family: 宋体">。比方说</span>IComparable(Of Object)<span style="font-family: 宋体">将能够反变成</span>IComparable(Of String)<span style="font-family: 宋体">。因为</span>IComparable(Of In T)<span style="font-family: 宋体">拥有</span>In<span style="font-family: 宋体">的修饰。接下来</span>IBar(Of Out T)<span style="font-family: 宋体">也将可以<strong>协变</strong>成</span>IBar(Of Out U)<span style="font-family: 宋体">，当且仅当</span>T<span style="font-family: 宋体">继承自</span>U<span style="font-family: 宋体">。比如</span>IEnumerable(Of String)<span style="font-family: 宋体">将能够协变成</span>IEnumerable(Of Object)<span style="font-family: 宋体">。注意达成协变和反变的条件仅仅是继承关系，而且必须都是引用类型。值类型泛型和引用类型泛型因为有不同的</span>JIT<span style="font-family: 宋体">已构建类型（</span>Constructed Type<span style="font-family: 宋体">），所以是不能运行时协变的。</span></p>
<p style="margin: 0in 0in 10pt"><span style="font-family: 宋体">综上所述，</span>VB10<span style="font-family: 宋体">目前放出来的主要改进就是一些语法方面的完善工作。</span>VB<span style="font-family: 宋体">从很久以前就已经为动态大潮做好了准备，</span>C#4<span style="font-family: 宋体">的大部分新特性（例如</span>dynamic<span style="font-family: 宋体">，可选参数，命名参数）全部都是</span>10<span style="font-family: 宋体">年前</span>VB<span style="font-family: 宋体">就已经拥有的。现在</span>VB<span style="font-family: 宋体">将传统的动态能力与新的</span>DLR<span style="font-family: 宋体">结合在一起，加上</span>XML<span style="font-family: 宋体">语法的卓越威力，必将成为</span>.NET 4<span style="font-family: 宋体">时代重要的动态语言。后续新特性，待官方发布后将继续研究和报道。</span></p>
<img src ="http://www.cnblogs.com/Ninputer/aggbug/1325602.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/48000/" target="_blank">数万名网友签名抗议星际争霸2取消局域网功能</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>用Lambda表达式进行函数式编程（续）：用C#实现Y组合子</title><link>http://www.cnblogs.com/Ninputer/archive/2007/11/26/972968.html</link><dc:creator>装配脑袋</dc:creator><author>装配脑袋</author><pubDate>Mon, 26 Nov 2007 09:14:00 GMT</pubDate><guid>http://www.cnblogs.com/Ninputer/archive/2007/11/26/972968.html</guid><wfw:comment>http://www.cnblogs.com/Ninputer/comments/972968.html</wfw:comment><comments>http://www.cnblogs.com/Ninputer/archive/2007/11/26/972968.html#Feedback</comments><slash:comments>20</slash:comments><wfw:commentRss>http://www.cnblogs.com/Ninputer/comments/commentRss/972968.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Ninputer/services/trackbacks/972968.html</trackback:ping><description><![CDATA[摘要: 上次发表了VS2008亮点：用Lambda表达式进行函数式编程这篇文章后，有些人提出希望看C#版。其实我本来想等大家多尝试下能否自己实现的，可惜没有太多人实际思考这个问题，是不是觉得函数式编程离我们的日常生活太远……不管怎么说，这次我将公布强类型语言C#实现不动点组合子Y的方法，以及类型推导的全过程。不喜欢强类型思考的朋友看本文一定要做好头晕的准备……&nbsp;&nbsp;<a href='http://www.cnblogs.com/Ninputer/archive/2007/11/26/972968.html'>阅读全文</a><img src ="http://www.cnblogs.com/Ninputer/aggbug/972968.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/47999/" target="_blank">Silverlight打造杰克逊纪念专题</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>VS2008亮点：用Lambda表达式进行函数式编程</title><link>http://www.cnblogs.com/Ninputer/archive/2007/11/23/970460.html</link><dc:creator>装配脑袋</dc:creator><author>装配脑袋</author><pubDate>Fri, 23 Nov 2007 13:15:00 GMT</pubDate><guid>http://www.cnblogs.com/Ninputer/archive/2007/11/23/970460.html</guid><wfw:comment>http://www.cnblogs.com/Ninputer/comments/970460.html</wfw:comment><comments>http://www.cnblogs.com/Ninputer/archive/2007/11/23/970460.html#Feedback</comments><slash:comments>46</slash:comments><wfw:commentRss>http://www.cnblogs.com/Ninputer/comments/commentRss/970460.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Ninputer/services/trackbacks/970460.html</trackback:ping><description><![CDATA[摘要: Visual Studio 2008正式发布了，我们.NET开发者也走进了新的.NET 3.5时代。相对于.NET 3.0中的Foundations，3.5的改进更注重编码体验了。新的Linq系列语法和Linq to Sql、Linq to Xml大大改变了我们访问数据的方式。但是纵观Linq系列语法，影响最大的要数Lambda表达式。虽然从渊源来讲Lambda表达式就是匿名函数的简化表示方法，但谁也想不到这一小小的语法给我们带来了整个Linq与众不同的查询式语法。<br>注意本文介绍的函数式编程思想比Linq中的更难，主要目的是为了启发思考，带来灵感。希望能坚持看到底哦。&nbsp;&nbsp;<a href='http://www.cnblogs.com/Ninputer/archive/2007/11/23/970460.html'>阅读全文</a><img src ="http://www.cnblogs.com/Ninputer/aggbug/970460.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/47998/" target="_blank">传诺基亚正在开发Android手机</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>.NET 2.0 CER学习笔记</title><link>http://www.cnblogs.com/Ninputer/archive/2006/06/30/learncer1.html</link><dc:creator>装配脑袋</dc:creator><author>装配脑袋</author><pubDate>Fri, 30 Jun 2006 07:54:00 GMT</pubDate><guid>http://www.cnblogs.com/Ninputer/archive/2006/06/30/learncer1.html</guid><wfw:comment>http://www.cnblogs.com/Ninputer/comments/439757.html</wfw:comment><comments>http://www.cnblogs.com/Ninputer/archive/2006/06/30/learncer1.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cnblogs.com/Ninputer/comments/commentRss/439757.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Ninputer/services/trackbacks/439757.html</trackback:ping><description><![CDATA[CER是.NET 2.0 CLR方面的重要改进，旨在帮助那些对稳定性高度苛刻的程序对付.NET Framework的不稳定因素。因为普通的程序很少会用到，所以一直没有对这个特性加以足够重视。现在碰巧在翻译书籍的过程中用到，就一起来学习一下。<br>首先，需要提到异步异常的问题。异步异常就是指OutOfMemoryException、StackOverflowException和ThreadAbortException等系统异常。说他们&#8220;异步&#8221;是因为他们可以在线程代码执行到任何地方的时候发生。一般的异常，比如FileNotFoundException是由代码自己产生的，因此可以用Try语句正常捕捉和处理。而异步异常则是CLR产生的。而且，这些异常都预示着非常严重的错误，代码自己通常都会手足无措。比方说内存耗尽了，代码自己即使Catch了也无济于事，都不知道刚刚哪一步出的问题，也不知道该怎么继续执行。ThreadAbortException通常是由Thread.Abort方法引发，如果要Abort的线程正在进行很关键的人物，比如修改一个全局对象的状态，那么发生ThreadAbortException可能会让整个程序的状态受损，进而产生错误的行为。因此，需要有种机制告诉CLR，我们要进行的事情很关键，不容打断，这就是CER——Constrained Execution Region。<br>声明CER很简单，先调用System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions()方法，再紧接一个Try...Catch...Finally块即可。注意，这个Try必须紧接着PrepareConstrainedRegions()方法，而且，<strong>只有Catch和Finally块的内容成为CER</strong>。如下所示<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">RuntimeHelpers.PrepareConstrainedRegions()<br></span><span style="COLOR: #0000ff">Try</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">Catch</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">'</span><span style="COLOR: #008000">注意，这里是CER</span><span style="COLOR: #008000"><br></span><span style="COLOR: #0000ff">Finally</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">'</span><span style="COLOR: #008000">这里也是CER</span><span style="COLOR: #008000"><br></span><span style="COLOR: #0000ff">End</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Try</span></div>
一般情况下都用Finally块来做CER。CER与普通代码不同，在CER执行期间CLR不能发出异步异常。因此CLR就必须采取一些措施。首先CER会将ThreadAbortException推迟到CER结束之后才发生，这比较容易做到。第二，为了避免OutOfMemoryException，CLR会将CER中用到的所有方法（注意，这里是从代码静态观察，而不是实际调用的方法）以及这些方法所调用到的所有方法全都编译成本地代码，然后根据情况预测可能的内存不足并提前到CER之前引发。然而，这个方法并不能对付堆栈益处错误，所以这个方法会事先保留48K的栈空间以防万一。然而根据MSDN文档，StackOverflowException还是可能会发生的。<br>为了确保CER这种原理能够工作，首先CER之内不能在堆上进行任何分配操作，包括后台进行的分配操作。除了不能用New分配引用类型的对象之外，也不能进行装箱、线程同步锁操作或者访问多维数组。<br>刚才介绍到，CLR会事先编译CER中所有用到的方法以及它们各自调用的所有方法。那么聪明的人一定能看出一个问题，那就是通过委托和虚函数机制调用的方法无法事先准确判断，因而就无从准备。因此，RuntimeHelpers还提供了两个方法——PrepareMethod和PrepareDelegate。调用之前务必用这两个方法准备所有虚函数的实际版本和委托变量。使用CER是需要极其小心准备的，因此不是随随便便使用的特性。RuntimeHelpers还有许多其它方法对应各种有变数的情况。总之，CER的宗旨就是在执行之前将所有可以知道的情况尽数分析透彻以便提前判断CER中的操作到底有没有可能顺利完成。<br>下面用ThreadAbortException来做一个试验，因为这个异常是最容易引发的：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">Imports</span><span style="COLOR: #000000">&nbsp;System.Runtime.CompilerServices<br><img src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">Imports</span><span style="COLOR: #000000">&nbsp;System.Threading<br><img src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top><br><img id=Codehighlighter1_66_818_Open_Image onclick="this.style.display='none'; Codehighlighter1_66_818_Open_Text.style.display='none'; Codehighlighter1_66_818_Closed_Image.style.display='inline'; Codehighlighter1_66_818_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_66_818_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_66_818_Closed_Text.style.display='none'; Codehighlighter1_66_818_Open_Image.style.display='inline'; Codehighlighter1_66_818_Open_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_66_818_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">Module&nbsp;Module1</span><span id=Codehighlighter1_66_818_Open_Text><span style="COLOR: #0000ff">Module</span><span style="COLOR: #000000">&nbsp;Module1<br><img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">Dim</span><span style="COLOR: #000000">&nbsp;globalArray()&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Integer</span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top><br><img id=Codehighlighter1_120_347_Open_Image onclick="this.style.display='none'; Codehighlighter1_120_347_Open_Text.style.display='none'; Codehighlighter1_120_347_Closed_Image.style.display='inline'; Codehighlighter1_120_347_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_120_347_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_120_347_Closed_Text.style.display='none'; Codehighlighter1_120_347_Open_Image.style.display='inline'; Codehighlighter1_120_347_Open_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_120_347_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">Sub&nbsp;Main()</span><span id=Codehighlighter1_120_347_Open_Text><span style="COLOR: #0000ff">Sub</span><span style="COLOR: #000000">&nbsp;Main()<br><img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;globalArray&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">New</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Integer</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">50000000</span><span style="COLOR: #000000">)&nbsp;{}<br><img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">Dim</span><span style="COLOR: #000000">&nbsp;t&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">New</span><span style="COLOR: #000000">&nbsp;Thread(</span><span style="COLOR: #0000ff">AddressOf</span><span style="COLOR: #000000">&nbsp;Thread1)<br><img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t.Start()<br><img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t.Abort()<br><img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t.Join()<br><img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(AllEquals(globalArray,&nbsp;</span><span style="COLOR: #000000">100</span><span style="COLOR: #000000">))<br><img src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">End&nbsp;Sub</span></span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top><br><img id=Codehighlighter1_354_579_Open_Image onclick="this.style.display='none'; Codehighlighter1_354_579_Open_Text.style.display='none'; Codehighlighter1_354_579_Closed_Image.style.display='inline'; Codehighlighter1_354_579_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_354_579_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_354_579_Closed_Text.style.display='none'; Codehighlighter1_354_579_Open_Image.style.display='inline'; Codehighlighter1_354_579_Open_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_354_579_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">Function&nbsp;AllEquals()</span><span id=Codehighlighter1_354_579_Open_Text><span style="COLOR: #0000ff">Function</span><span style="COLOR: #000000">&nbsp;AllEquals(Of&nbsp;T)(</span><span style="COLOR: #0000ff">ByVal</span><span style="COLOR: #000000">&nbsp;arr()&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;T,&nbsp;</span><span style="COLOR: #0000ff">ByVal</span><span style="COLOR: #000000">&nbsp;value&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;T)&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Boolean</span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">For</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Integer</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">To</span><span style="COLOR: #000000">&nbsp;arr.Length&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">If</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Not</span><span style="COLOR: #000000">&nbsp;arr(i).Equals(value)&nbsp;</span><span style="COLOR: #0000ff">Then</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">False</span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">Next</span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">Return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">True</span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">End&nbsp;Function</span></span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top><br><img id=Codehighlighter1_586_806_Open_Image onclick="this.style.display='none'; Codehighlighter1_586_806_Open_Text.style.display='none'; Codehighlighter1_586_806_Closed_Image.style.display='inline'; Codehighlighter1_586_806_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_586_806_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_586_806_Closed_Text.style.display='none'; Codehighlighter1_586_806_Open_Image.style.display='inline'; Codehighlighter1_586_806_Open_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_586_806_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">Sub&nbsp;Thread1()</span><span id=Codehighlighter1_586_806_Open_Text><span style="COLOR: #0000ff">Sub</span><span style="COLOR: #000000">&nbsp;Thread1()<br><img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RuntimeHelpers.PrepareConstrainedRegions()<br><img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">Try</span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">Finally</span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">For</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Integer</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">To</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">50000000</span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;globalArray(i)&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">100</span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">Next</span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">End</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Try</span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">End&nbsp;Sub</span></span><span style="COLOR: #000000"><br><img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top></span><span style="COLOR: #0000ff">End&nbsp;Module</span></span></div>
&nbsp;先把准备CER的代码注释掉，可以发现这个方法不是总能执行成功的，ThreadAbortException可能会将数组的操作打断，以至于留下不正常的状态。如果在你的计算机上该方法不会失败，可以尝试改变数组的大小。接下来应用CER，会发现出现异常时程序执行的速度剧烈下降，但是最终方法总能够成功地完成。这就是CER所带来的好处。<br><img src ="http://www.cnblogs.com/Ninputer/aggbug/439757.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/47996/" target="_blank">7月编程语言排行榜</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>一些支离破碎的泛型反射技巧</title><link>http://www.cnblogs.com/Ninputer/archive/2006/06/02/415458.html</link><dc:creator>装配脑袋</dc:creator><author>装配脑袋</author><pubDate>Fri, 02 Jun 2006 00:48:00 GMT</pubDate><guid>http://www.cnblogs.com/Ninputer/archive/2006/06/02/415458.html</guid><wfw:comment>http://www.cnblogs.com/Ninputer/comments/415458.html</wfw:comment><comments>http://www.cnblogs.com/Ninputer/archive/2006/06/02/415458.html#Feedback</comments><slash:comments>11</slash:comments><wfw:commentRss>http://www.cnblogs.com/Ninputer/comments/commentRss/415458.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Ninputer/services/trackbacks/415458.html</trackback:ping><description><![CDATA[本文为一些泛型反射技巧的简单罗列，为日后的文章做准备。<br>1、如何获得一个封闭构造类型（closed constructed type）的Type对象？<br>假设有如下的类型：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;TestType</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">T</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;TestType</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">T,&nbsp;U</span><span style="COLOR: #000000">&gt;</span></div>
如果要获得封闭构造类型的Type对象，那么只需要用C#的typeof运算符，或者VB的GetType运算符作用于具体类型即可：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008000">//</span><span style="COLOR: #008000">C#</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">Type&nbsp;t1&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">typeof</span><span style="COLOR: #000000">(TestType</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">);</span></div>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008000">'</span><span style="COLOR: #008000">VB</span><span style="COLOR: #008000"><br></span><span style="COLOR: #0000ff">Dim</span><span style="COLOR: #000000">&nbsp;t2&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;Type&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">GetType</span><span style="COLOR: #000000">(TestType(Of&nbsp;</span><span style="COLOR: #0000ff">String</span><span style="COLOR: #000000">))</span></div>
<br>2、如何获取一个泛型类型（generic type）的Type对象？<br>所谓泛型类型，就是有类型参数，但类型参数还未指定的原始定义。我们不能用TestType&lt;T&gt;这样的语法，因为T在我们的上下文中不存在。这时，可以用空的尖括号（C#）或空的Of语句（VB）来获取。<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">Type&nbsp;t1&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">typeof</span><span style="COLOR: #000000">(TestType</span><span style="COLOR: #000000">&lt;&gt;</span><span style="COLOR: #000000">);<br>Type&nbsp;t2&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">typeof</span><span style="COLOR: #000000">(TestType</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">);</span></div>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">Dim</span><span style="COLOR: #000000">&nbsp;t1,&nbsp;t2&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;Type<br>t1&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">GetType</span><span style="COLOR: #000000">(TestType(Of&nbsp;))<br>t2&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">GetType</span><span style="COLOR: #000000">(TestType(Of&nbsp;,))</span></div>
注意，我们可以用逗号来区别类型参数的个数。这就表明，泛型类型只能按类型参数的多少来重载，而不管有何种约束之类。这里获得的Type，就是类型参数未指定的泛型类型。<br><br>3、如何从构造类型的Type对象生成泛型类型的Type对象？<br>Type类的新增方法可以做到。<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008000">//</span><span style="COLOR: #008000">C#</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">Type&nbsp;ct&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">typeof</span><span style="COLOR: #000000">(List</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">);<br><br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">Get&nbsp;generic&nbsp;type&nbsp;definition</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">Type&nbsp;gt&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;ct.GetGenericTypeDefinition();</span></div>
<br>4、如何获取类型参数的Type对象？<br>泛型类型的T, U等类型参数，以及运行中的实际取值，都是可以从Type对象获取的。<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008000">'</span><span style="COLOR: #008000">VB</span><span style="COLOR: #008000"><br></span><span style="COLOR: #0000ff">Dim</span><span style="COLOR: #000000">&nbsp;t&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;Type&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">GetType</span><span style="COLOR: #000000">(List(Of&nbsp;</span><span style="COLOR: #0000ff">Integer</span><span style="COLOR: #000000">))<br><br></span><span style="COLOR: #008000">'</span><span style="COLOR: #008000">Get&nbsp;the&nbsp;generic&nbsp;arguments,&nbsp;an&nbsp;array</span><span style="COLOR: #008000"><br></span><span style="COLOR: #0000ff">Dim</span><span style="COLOR: #000000">&nbsp;typeArgs&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;Type()&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;t.GetGenericArguments()<br></span><span style="COLOR: #008000">'</span><span style="COLOR: #008000">Get&nbsp;the&nbsp;first&nbsp;argument:&nbsp;Integer&nbsp;in&nbsp;this&nbsp;case</span><span style="COLOR: #008000"><br></span><span style="COLOR: #0000ff">Dim</span><span style="COLOR: #000000">&nbsp;tArg0&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;Type&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;typeArgs(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)</span></div>
<br>5、从泛型类型Type对象生成构造类型的Type对象。<br>通常可以用来从一种构造类型生成另一种构造类型<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008000">//</span><span style="COLOR: #008000">C#</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">Type&nbsp;ct&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">typeof</span><span style="COLOR: #000000">(List</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">);<br>Type&nbsp;gt&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;ct.GetGenericTypeDefinition();<br><br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">Make&nbsp;another&nbsp;constructed&nbsp;type<br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">The&nbsp;List&lt;string&gt;&nbsp;in&nbsp;this&nbsp;case</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">Type&nbsp;ct2&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;gt.MakeGenericType(</span><span style="COLOR: #0000ff">typeof</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">));</span></div>
<br>6、如何取一个开放构造类型（open constructed type）的Type对象？<br>开放构造类型是最难处理的一个，因为他们的类型参数已经指定，但没有指定为具体类型，而是指定为其他泛型类型的类型参数。这种类型在进行反射重载选取以及反射发出（Reflection Emit）操作的时候尤为重要。我们的手法就是，先从宿主泛型类型的定义中获取类型参数的类型，然后再建造出开放构造类型。这里，我们获得List&lt;T&gt;的构造函数的参数，IEnumerable&lt;T&gt;的类型，注意这里的T是List&lt;T&gt;所定义的，而不是泛型IEnumerable&lt;T&gt;自己的类型参数<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008000">'</span><span style="COLOR: #008000">The&nbsp;generic&nbsp;type&nbsp;of&nbsp;List(Of&nbsp;T)</span><span style="COLOR: #008000"><br></span><span style="COLOR: #0000ff">Dim</span><span style="COLOR: #000000">&nbsp;tlist&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;Type&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">GetType</span><span style="COLOR: #000000">(List(Of&nbsp;))<br><br></span><span style="COLOR: #008000">'</span><span style="COLOR: #008000">Get&nbsp;the&nbsp;"T"&nbsp;of&nbsp;List(Of&nbsp;T)</span><span style="COLOR: #008000"><br></span><span style="COLOR: #0000ff">Dim</span><span style="COLOR: #000000">&nbsp;typeParam&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;Type&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;tlist.GetGenericArguments()(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)<br><br></span><span style="COLOR: #008000">'</span><span style="COLOR: #008000">the&nbsp;generic&nbsp;type&nbsp;of&nbsp;IEnumerable(Of&nbsp;T)</span><span style="COLOR: #008000"><br></span><span style="COLOR: #0000ff">Dim</span><span style="COLOR: #000000">&nbsp;tienum&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;Type&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">GetType</span><span style="COLOR: #000000">(IEnumerable(Of&nbsp;))<br><br></span><span style="COLOR: #008000">'</span><span style="COLOR: #008000">make&nbsp;the&nbsp;open&nbsp;constructed&nbsp;type</span><span style="COLOR: #008000"><br></span><span style="COLOR: #0000ff">Dim</span><span style="COLOR: #000000">&nbsp;tienumOpen&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;Type&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;tienum.MakeGenericType(typeParam)<br><br></span><span style="COLOR: #008000">'</span><span style="COLOR: #008000">只有用这种方法获得开放构造类型</span><span style="COLOR: #008000"><br>'</span><span style="COLOR: #008000">你才能用这个语法获得真正想要的构造函数定义</span><span style="COLOR: #008000"><br>'</span><span style="COLOR: #008000">因为构造函数定义里IEnumerable(Of&nbsp;T)是一个开放构造类型</span><span style="COLOR: #008000"><br></span><span style="COLOR: #0000ff">Dim</span><span style="COLOR: #000000">&nbsp;c&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;ConstructorInfo&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;_<br>&nbsp;&nbsp;&nbsp;&nbsp;tlist.GetConstructor(</span><span style="COLOR: #0000ff">New</span><span style="COLOR: #000000">&nbsp;Type()&nbsp;{tienumOpen})</span></div>
<br>大家可以回去结合试验理解这些用法。 
<img src ="http://www.cnblogs.com/Ninputer/aggbug/415458.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/47995/" target="_blank">Google Voice 上手</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>泛型技巧系列：类型字典和Type Traits</title><link>http://www.cnblogs.com/Ninputer/archive/2006/04/14/374921.html</link><dc:creator>装配脑袋</dc:creator><author>装配脑袋</author><pubDate>Fri, 14 Apr 2006 02:12:00 GMT</pubDate><guid>http://www.cnblogs.com/Ninputer/archive/2006/04/14/374921.html</guid><wfw:comment>http://www.cnblogs.com/Ninputer/comments/374921.html</wfw:comment><comments>http://www.cnblogs.com/Ninputer/archive/2006/04/14/374921.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cnblogs.com/Ninputer/comments/commentRss/374921.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Ninputer/services/trackbacks/374921.html</trackback:ping><description><![CDATA[<p>注意：未经许可，本系列禁止转载。<br><br>本文所介绍的技巧，是我在研究泛型开发不久就发现并成功运用的技巧。这个技巧是突破.NET泛型限制，达到&#8220;看上去很美&#8221;境界的法宝。当然本方法也存在重大缺陷，后面我会逐一介绍。本文同时使用VB和C#语法，以下是泛型方面VB和C#的语法小小对照：<br>
<table style="WIDTH: 320px; BORDER-COLLAPSE: collapse" cellSpacing=0 cellPadding=3 border=1>
    <tbody>
        <tr>
            <td>VB</td>
            <td>C#</td>
        </tr>
        <tr>
            <td>Identifier<strong>(Of T)</strong></td>
            <td>Identifier<strong>&lt;T&gt;</strong></td>
        </tr>
        <tr>
            <td>Identifier<strong>(Of T As C)</strong></td>
            <td>Identifier<strong>&lt;T&gt; where T : C</strong></td>
        </tr>
    </tbody>
</table>
<br>上次我们介绍了约束模型的缺陷和使用外部辅助类代替约束的手法。现在我们继续研究该手法。如上次所说，基本数值类型Integer, Long和Double等并没有实现什么公共的接口以实现普通加减乘除等运算；在泛型类和方法中，类型参数的变量之间也不允许使用+、-等运算符，所以我们别无选择，只能使用外部辅助类。以下就是我编写的辅助类Calculator。他是这样工作的：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">Function</span><span style="COLOR: #000000">&nbsp;Add(Of&nbsp;T)(a&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;T,&nbsp;b&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;T)</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;T<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">Return</span><span style="COLOR: #000000">&nbsp;Calculator(Of&nbsp;T).Default.Add(a,&nbsp;b)<br></span><span style="COLOR: #0000ff">End&nbsp;Function</span><span style="COLOR: #000000"><br><br></span><span style="COLOR: #008000">'</span><span style="COLOR: #008000">在另一个方法中</span><span style="COLOR: #008000"><br></span><span style="COLOR: #0000ff">Dim</span><span style="COLOR: #000000">&nbsp;c&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Integer</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;Add(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">)<br></span><span style="COLOR: #0000ff">Dim</span><span style="COLOR: #000000">&nbsp;d&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Double</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;Add(</span><span style="COLOR: #000000">1.5</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">888.0</span><span style="COLOR: #000000">)</span></div>
<br>我们看到，Calculator(Of T).Default能够在T确定为Integer或Double的时候分别给出正确的整数相加及浮点数相加运算。.NET泛型本身是缺乏这种编译时类型选择功能的，也就是说，无法根据类型参数T的不同自动选择不同的代码执行。那么是不是只能用运行时If语句加类型判断了呢？如果是那样，运行时效率必然难以保证，同时也失去了使用泛型的意义。所以我们得求助一个工具——类型字典。<br><br>&#8220;类型字典&#8221;这个词是我根据其特性杜撰的，它其实利用到.NET泛型很重要的一个特性：泛型类的静态字段。如果有一个泛型类型A(Of T)，那么它的每一个<strong>封闭构造类型（Closed Constructed Type）</strong>独享一组静态字段的取值。也就是说，假设X是A(Of T)的静态字段（VB中的Shared或C#中的static），那么A(Of Integer).X与A(Of String).X是互相独立的两个字段，改变一个的值不会影响到另一个。这样就给我们提供了一个极为便利的条件，我们可以利用泛型类型的静态字段，为类型参数的每一组封闭取值（封闭的意思是所有取值为非泛型类型或泛型封闭构造类型）保存一个字段的值。简单地说，这就相当于以类型作为关键字，建立了一个字典，其值则是一个对象。以下为C#语法的一个小小的例子：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;TypeDict</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">T</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;Value;<br>}<br><br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">在代码中，我们可以为每个封闭类型保存一个int<br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">这相当于一个&nbsp;类型到int&nbsp;的字典</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">TypeDict</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">.Value&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br>TypeDict</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">.Value&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">;<br>TypeDict</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">List</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&gt;&gt;</span><span style="COLOR: #000000">.Value&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">;<br>TypeDict</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">List</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">double</span><span style="COLOR: #000000">&gt;&gt;</span><span style="COLOR: #000000">.Value&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">4</span><span style="COLOR: #000000">;</span></div>
<br>从类型查询到其相应的值，只有访问一个静态字段的代价，可谓极低。下面我们就利用这个优势，实现根据类型参数的不同，自动给出适合该类型的算术运算功能。我们统称这种类型参数取不同取值，类的功能就自动变化的功能为type traits，意为&#8220;类型特征&#8221;。.NET泛型不支持特化，因此不能做编译期选择的type trait，只能将这个过程推迟到运行期。为了减少运行期的消耗，我们采用首次运行进行类型判断，然后用类型字典保存判断结果的手法，我称之为<strong>首次缓存的拟type traits</strong>。下面用四则运算为例介绍做法：为了简化，我们现在只考虑四则运算功能中的加法。以下是在同类型上实现加法的接口：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">Public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Interface</span><span style="COLOR: #000000">&nbsp;ICalculator(Of&nbsp;T)<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">Function</span><span style="COLOR: #000000">&nbsp;Add(a&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;T,&nbsp;b&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;T)</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;T<br>&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.cnblogs.com/Images/dot.gif"><br></span><span style="COLOR: #0000ff">End&nbsp;Interface</span></div>
<br>我们要给ICalculator接口提供一个具有type trait功能的默认实现，首先声明一个类型：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">Public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">MustInherit</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Class</span><span style="COLOR: #000000">&nbsp;Calculator(Of&nbsp;T)<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">Implements</span><span style="COLOR: #000000">&nbsp;ICalculator(Of&nbsp;T)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">Public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">MustOverride</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Function</span><span style="COLOR: #000000">&nbsp;Add(a&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;T,&nbsp;b&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;T)&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;T&nbsp;_<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">Implements</span><span style="COLOR: #000000">&nbsp;ICalculator(Of&nbsp;T).Add<br>&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #0000ff">End&nbsp;Class</span></div>
<br>注意这是一个抽象类，我们还没有写完他，但当前要做的事情是，为Integer，Double和T（代表未知类型）编写三个特化子类，分别封装Integer, Double和未知类型的加法。<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">Class</span><span style="COLOR: #000000">&nbsp;IntegerCalc<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">Inherits</span><span style="COLOR: #000000">&nbsp;Calculator(Of&nbsp;</span><span style="COLOR: #0000ff">Integer</span><span style="COLOR: #000000">)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">Public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Overrides</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Function</span><span style="COLOR: #000000">&nbsp;Add(</span><span style="COLOR: #0000ff">ByVal</span><span style="COLOR: #000000">&nbsp;a&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Integer</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #0000ff">ByVal</span><span style="COLOR: #000000">&nbsp;b&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Integer</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Integer</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">Return</span><span style="COLOR: #000000">&nbsp;a&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;b<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">End&nbsp;Function</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">End&nbsp;Class</span><span style="COLOR: #000000"><br><br></span><span style="COLOR: #0000ff">Class</span><span style="COLOR: #000000">&nbsp;DoubleCalc<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">Inherits</span><span style="COLOR: #000000">&nbsp;Calculator(Of&nbsp;</span><span style="COLOR: #0000ff">Double</span><span style="COLOR: #000000">)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">Public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Overrides</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Function</span><span style="COLOR: #000000">&nbsp;Add(</span><span style="COLOR: #0000ff">ByVal</span><span style="COLOR: #000000">&nbsp;a&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Double</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #0000ff">ByVal</span><span style="COLOR: #000000">&nbsp;b&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Double</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Double</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">Return</span><span style="COLOR: #000000">&nbsp;a&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;b<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">End&nbsp;Function</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">End&nbsp;Class</span><span style="COLOR: #000000"><br><br></span><span style="COLOR: #0000ff">Class</span><span style="COLOR: #000000">&nbsp;ObjectCalc(Of&nbsp;T)<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">Inherits</span><span style="COLOR: #000000">&nbsp;Calculator(Of&nbsp;T)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">Public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Overrides</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Function</span><span style="COLOR: #000000">&nbsp;Add(</span><span style="COLOR: #0000ff">ByVal</span><span style="COLOR: #000000">&nbsp;a&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;T,&nbsp;</span><span style="COLOR: #0000ff">ByVal</span><span style="COLOR: #000000">&nbsp;b&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;T)&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;T<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">'</span><span style="COLOR: #008000">后期绑定的加法运算</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">'</span><span style="COLOR: #008000">VB的后期绑定支持运算符重载</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">Return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">DirectCast</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">CObj</span><span style="COLOR: #000000">(a)&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">CObj</span><span style="COLOR: #000000">(b),&nbsp;T)<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">End&nbsp;Function</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">End&nbsp;Class</span></div>
<br>给特殊类型的子类编写加法出奇的容易，因为类型变成了已知类型，因此运算符也就能够允许使用。注意我我们给ObjectCalc编写的加法过程使用了后期绑定加法，因此可以支持任何重载+号的类型，但是他的速度要比IntegerCalc和DoubleCalc中的做法慢很多倍。因此在实际代码中，我为.NET中具有算术加法概念的许多类型，如整型，浮点型，Decimal和Nullable类型都做了特殊子类。而ObjectCalc则为那些没有考虑到的类型提供低性能，但仍起作用的最低保证。 下面我们用If语句模拟编译期的类型选择机制，并保存在Calculator(Of T)的静态字段里，做成类型字典。修改Calculator如下<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">Public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">MustInherit</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Class</span><span style="COLOR: #000000">&nbsp;Calculator(Of&nbsp;T)<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">Implements</span><span style="COLOR: #000000">&nbsp;ICalculator(Of&nbsp;T)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">Public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">MustOverride</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Function</span><span style="COLOR: #000000">&nbsp;Add(</span><span style="COLOR: #0000ff">ByVal</span><span style="COLOR: #000000">&nbsp;a&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;T,&nbsp;</span><span style="COLOR: #0000ff">ByVal</span><span style="COLOR: #000000">&nbsp;b&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;T)&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;T&nbsp;_<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">Implements</span><span style="COLOR: #000000">&nbsp;ICalculator(Of&nbsp;T).Add<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">'</span><span style="COLOR: #008000">保存类型T的字典值</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">Private</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Shared</span><span style="COLOR: #000000">&nbsp;defaultCalc&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;Calculator(Of&nbsp;T)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">Public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Shared</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">ReadOnly</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Property</span><span style="COLOR: #000000">&nbsp;[</span><span style="COLOR: #0000ff">Default</span><span style="COLOR: #000000">]()&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;Calculator(Of&nbsp;T)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">Get</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">If</span><span style="COLOR: #000000">&nbsp;defaultCalc&nbsp;</span><span style="COLOR: #0000ff">Is</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Nothing</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Then</span><span style="COLOR: #000000">&nbsp;CreateCalculator()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">Return</span><span style="COLOR: #000000">&nbsp;defaultCalc<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">End</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Get</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">End&nbsp;Property</span><span style="COLOR: #000000"><br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">Private</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Shared</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Sub</span><span style="COLOR: #000000">&nbsp;CreateCalculator()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">Dim</span><span style="COLOR: #000000">&nbsp;calcObj&nbsp;</span><span style="COLOR: #0000ff">As</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">Object</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">'</span><span style="COLOR: #008000">根据类型进行特殊子类的指派</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">If</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">GetType</span><span style="COLOR: #000000">(T).Equals(</span><span style="COLOR: #0000ff">GetType</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">Integer</span><span style="COLOR: #000000">))&nbsp;</span><span style="COLOR: #0000ff">Then</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;calcObj&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">New</span><span style="COLOR: #000000">&nbsp;IntegerCalc<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">ElseIf</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">GetType</span><span style="COLOR: #000000">(T).Equals(</span><span style="COLOR: #0000ff">GetType</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">Double</span><span style="COLOR: #000000">))&nbsp;</span><span style="COLOR: #0000ff">Then</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;calcObj&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">New</span><span style="COLOR: #000000">&nbsp;DoubleCalc<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">Else</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">'</span><span style="COLOR: #008000">未知类型</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;calcObj&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">New</span><span style="COLOR: #000000">&nbsp;ObjectCalc(Of&nbsp;T)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">End</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">If</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">'</span><span style="COLOR: #008000">强行让编译器认为我们选择类型就是T</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;defaultCalc&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">DirectCast</span><span style="COLOR: #000000">(calcObj,&nbsp;Calculator(Of&nbsp;T))<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">End&nbsp;Sub</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">End&nbsp;Class</span></div>
<br>下面我们来看看这是如何工作的，假设我们要进行Integer的计算，那么首先写下Calculator(Of Integer).Default，这是第一次运行，所以它调用CreateCalculator方法。这个方法利用GetType运算符（C#的typeof）判断T是否是我们写过的特殊子类实现的类型，并且给静态字段defaultCalc分配一个特殊子类。这时候Default的值其实就是IntegerCalc的实例。当你第二次运行Calculator(Of Integer).Default的时候，缓存在Calculator(Of Integer)类型字典中的IntegerCalc实例会被直接调用，不再会进行第一次的类型判断。也就是说从第二次起，我们Integer运算的加法就可以好像编译期选择的那样，全速执行了。<br><br>类型字典+首次缓存的拟type traits可以漂亮地做出自动根据类型进行选择的功能，但是他也不是没有缺陷的。首先是这种类型选择不能轻易的扩展。假如将Calculator的代码做到类库里，那么从外部想给他加入一个特殊类型子类是无法轻易做到的，因为基于If的判断语句不易扩展，改进的做法可能通过一个（普通）字典作登记。或者结合面向对象，不采用这种方法扩充，而由用户自行实现ICalculator，然后取代默认Calculator（这正是.NET Framework和VBF采用的做法）。第二个缺陷是保存在静态字段中的对象不会被清理，这样就会越用越多，占据内存。好在这种用于计算或比较类的对象都很小。<br><br>下一次，我们讨论利用反射操纵泛型类型，以达成更巧妙的设计。 
<img src ="http://www.cnblogs.com/Ninputer/aggbug/374921.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/47994/" target="_blank">Google号召社区力量为互联网加速</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>趣味程序：打印自己代码的程序</title><link>http://www.cnblogs.com/Ninputer/archive/2006/04/04/366554.html</link><dc:creator>装配脑袋</dc:creator><author>装配脑袋</author><pubDate>Tue, 04 Apr 2006 06:39:00 GMT</pubDate><guid>http://www.cnblogs.com/Ninputer/archive/2006/04/04/366554.html</guid><wfw:comment>http://www.cnblogs.com/Ninputer/comments/366554.html</wfw:comment><comments>http://www.cnblogs.com/Ninputer/archive/2006/04/04/366554.html#Feedback</comments><slash:comments>14</slash:comments><wfw:commentRss>http://www.cnblogs.com/Ninputer/comments/commentRss/366554.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Ninputer/services/trackbacks/366554.html</trackback:ping><description><![CDATA[在CSDN上看到了这道题<a href="http://community.csdn.net/Expert/topic/4654/4654528.xml">http://community.csdn.net/Expert/topic/4654/4654528.xml</a><br>是写一小段程序，打印自己的代码。按我的理解，这里应当不能利用元数据或者文件操作，要完全使用程序代码生成一段和自己的代码一模一样的字符串。我写了几个版本，这些程序运行出来的结果都是打印所贴代码本身，大家可以试试看，娱乐一下，仅此而已。<br><br>C#版，为简化字符串操作，该程序只有一行。<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;P{</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Main(){</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;s</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">class&nbsp;P{{static&nbsp;void&nbsp;Main(){{string&nbsp;s={1}{0}{1};System.Console.WriteLine(s,s,(char)34);}}}}</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;System.Console.WriteLine(s,s,(</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">34</span><span style="COLOR: #000000">);}}</span></div>
我已经写不出比这个还短，同时能打印自己代码的C#程序了。<br><br>VB版<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">Module</span><span style="COLOR: #000000">&nbsp;M:</span><span style="COLOR: #0000ff">Dim</span><span style="COLOR: #000000">&nbsp;c$&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Module&nbsp;M:Dim&nbsp;c$&nbsp;=&nbsp;{2}{0}{2}{1}Sub&nbsp;Main(){1}Console.WriteLine(c,c,vbCrLf,Chr(34)){1}End&nbsp;Sub:End&nbsp;Module</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">Sub</span><span style="COLOR: #000000">&nbsp;Main()<br>Console.WriteLine(c,c,vbCrLf,</span><span style="COLOR: #0000ff">Chr</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">34</span><span style="COLOR: #000000">))<br></span><span style="COLOR: #0000ff">End&nbsp;Sub</span><span style="COLOR: #000000">:</span><span style="COLOR: #0000ff">End&nbsp;Module</span></div>
同样，为了简化字符串操作，压缩了空格和换行。这也是我能写出最短的VB版本。<br><br>Python版<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">print</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">lambda</span><span style="COLOR: #000000">&nbsp;s:&nbsp;s.replace(chr(</span><span style="COLOR: #000000">042</span><span style="COLOR: #000000">),chr(</span><span style="COLOR: #000000">047</span><span style="COLOR: #000000">))</span><span style="COLOR: #000000">%</span><span style="COLOR: #000000">s)(</span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">print&nbsp;(lambda&nbsp;s:&nbsp;s.replace(chr(042),&nbsp;chr(047))%%s)("%s")</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000">)</span></div>
我的Python用的不是十分熟练，因此这个Python版本恐怕还不是最短的版本。不知道在座Python高手们能不能写出更精妙的打印自己代码的程序。
<img src ="http://www.cnblogs.com/Ninputer/aggbug/366554.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/47989/" target="_blank">Twitter无处不在 魔兽世界Twitter发送器插件发布</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item><item><title>Excel开发：简化工作表中选定区域的操作。</title><link>http://www.cnblogs.com/Ninputer/archive/2006/03/23/356613.html</link><dc:creator>装配脑袋</dc:creator><author>装配脑袋</author><pubDate>Thu, 23 Mar 2006 03:47:00 GMT</pubDate><guid>http://www.cnblogs.com/Ninputer/archive/2006/03/23/356613.html</guid><wfw:comment>http://www.cnblogs.com/Ninputer/comments/356613.html</wfw:comment><comments>http://www.cnblogs.com/Ninputer/archive/2006/03/23/356613.html#Feedback</comments><slash:comments>9</slash:comments><wfw:commentRss>http://www.cnblogs.com/Ninputer/comments/commentRss/356613.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Ninputer/services/trackbacks/356613.html</trackback:ping><description><![CDATA[摘要: 一个VSTO2005开发Excel项目的小技巧，用包装类简化Range的操作，可解析和生成Excel识别的地址字符串。&nbsp;&nbsp;<a href='http://www.cnblogs.com/Ninputer/archive/2006/03/23/356613.html'>阅读全文</a><img src ="http://www.cnblogs.com/Ninputer/aggbug/356613.html?type=1" width = "1" height = "1" /><br/><br/>--------------------------<br/>新闻：<a href="http://news.cnblogs.com/n/47988/" target="_blank">Firefox 3.5匆忙推出漏洞多 Mozilla本月将更新</a><br/>网站导航: <a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://dotnet.cnblogs.com" target="_blank">.NET频道</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://zzk.cnblogs.com" target="_blank">找找看</a>]]></description></item></channel></rss>