C# 4.0下的新特性

<p>回顾C#发展的历史,C#1.0完全是模仿Java,并保留了C/C++的一些特性如struct,新学者很容易上手;C#2.0加入了泛型,也与Java1.5的泛型如出一辙;C#3.0加入了一堆语法糖,并在没有修改CLR的情况下引入了Linq,简直是神来之笔,虽然很多项目出于各种各样如性能之类的原因没有采用,但非常适合小型程序的快速开发,减轻了程序员的工作量,也提高了代码的可读性;C#4.0增加了动态语言的特性,从里面可以看到很多javascript、python这些动态语言的影子。虽然越来越偏离静态语言的道路,但从另一个角度来说,这些特性也都是为了提高程序员的生产力。至于被接受与否,还是让时间来说话吧。<br> PS:这里面还有一点版本号的小插曲——VS2008所对应的.Net Framework是3.5,C#是3.0,CLR是2.0,及其混乱,MS终于下决心在VS2010中把这三个版本号都统一成了4.0,于是CLR3不知所终……</p>
<p><strong><span style="font-size: medium;">Dynamically Typed Object<br><br></span></strong>  C#4.0加入了dynamic关键字,可以申明一个变量的static类型为dynamic(有点绕口)。<br><br>  在3.0及之前,如果你不知道一个变量的类型,而要去调用它的一个方法,一般会用到反射: </p>
<div class="blockcode">
<em>复制内容到剪贴板</em>
<h5>代码:</h5>
<code id="code0">object calc = GetCalculator();<br>Type calcType = calc.GetType();<br>object res = calcType.InvokeMember("Add",<br>BindingFlags.InvokeMethod, null,<br>new object[] { 10, 20 });<br>int sum = Convert.ToInt32(res);</code>
</div>
<p>有了dynamic,就可以把上面代码简化为: </p>
<div class="blockcode">
<em>复制内容到剪贴板</em>
<h5>代码:</h5>
<code id="code1">dynamic calc = GetCalculator();<br>int sum = calc.Add(10, 20);</code>
</div>
<p>使用dynamic的好处在于,可以不去关心对象是来源于COM, Iron<span class="t_tag">Python</span>, HTML DOM或者反射,只要知道有什么方法可以调用就可以了,剩下的工作可以留给runtime。下面是调用IronPython类的例子: </p>
<div class="blockcode">
<em>复制内容到剪贴板</em>
<h5>代码:</h5>
<code id="code2">ScriptRuntime py = Python.CreateRuntime();<br>dynamic helloworld = py.UseFile("helloworld.py");<br>Console.WriteLine("helloworld.py loaded!");</code>
</div>
<p>dynamic也可以用在变量的传递中,runtime会自动选择一个最匹配的overload方法。<br><br>这里有一个demo:把一段javascript代码拷到C#文件中,将var改成dynamic,function改成void,再改一下构造函数的调用方式(new type()改为win.New.type()),去掉javascript中的win.前缀(因为这已经是C#的方法了),就可以直接运行了。<br><br>  dynamic的实现是基于IDynamicObject接口和DynamicObject抽象类。而动态方法、属性的调用都被转为了GetMember、Invoke等方法的调用。 </p>
<div class="blockcode">
<em>复制内容到剪贴板</em>
<h5>代码:</h5>
<code id="code3">public abstract class DynamicObject : IDynamicObject<br>{<br>public virtual object GetMember(GetMemberBinder info);<br>public virtual object SetMember(SetMemberBinder info, object value);<br>public virtual object DeleteMember(DeleteMemberBinder info); public virtual object UnaryOperation(UnaryOperationBinder info);<br>public virtual object BinaryOperation(BinaryOperationBinder info, object arg);<br>public virtual object Convert(ConvertBinder info); public virtual object Invoke(InvokeBinder info, object[] args);<br>public virtual object InvokeMember(InvokeMemberBinder info, object[] args);<br>public virtual object CreateInstance(CreateInstanceBinder info, object[] args); public virtual object GetIndex(GetIndexBinder info, object[] indices);<br>public virtual object SetIndex(SetIndexBinder info, object[] indices, object value);<br>public virtual object DeleteIndex(DeleteIndexBinder info, object[] indices); public MetaObject IDynamicObject.GetMetaObject();<br>}</code>
</div>
<p><span style="font-size: medium;"><strong>Named and optional parameters</strong></span><br><br>  这似乎不是什么很难实现或很新颖的特性,只要编译器的支持就可以(VB很早就支持了)。估计加入的原因是群众的呼声太高了。<br><br>  带有可选参数方法的声明: </p>
<div class="blockcode">
<em>复制内容到剪贴板</em>
<h5>代码:</h5>
<code id="code4">public StreamReader OpenTextFile(<br>string path,<br>Encoding encoding = null,<br>bool detectEncoding = true,<br>int bufferSize = 1024);</code>
</div>
<p>命名参数必须在最后使用: </p>
<div class="blockcode">
<em>复制内容到剪贴板</em>
<h5>代码:</h5>
<code id="code5">OpenTextFile("foo.txt", Encoding.UTF8, bufferSize: 4096);</code>
</div>
<p>顺序不限: </p>
<div class="blockcode">
<em>复制内容到剪贴板</em>
<h5>代码:</h5>
<code id="code6">OpenTextFile(bufferSize: 4096, path: "foo.txt", detectEncoding: false);</code>
</div>
<p><span style="font-size: medium;"><strong>Improved COM Interoperability</strong></span><br><br>  在C#中在调用COM对象如office对象时,经常需要写一堆不必要的参数: </p>
<div class="blockcode">
<em>复制内容到剪贴板</em>
<h5>代码:</h5>
<code id="code7">object fileName = "Test.docx";<br>object missing= System.Reflection.Missing.Value;<br>doc.SaveAs(ref fileName,<br>ref missing, ref missing, ref missing,<br>ref missing, ref missing, ref missing,<br>ref missing, ref missing, ref missing,<br>ref missing, ref missing, ref missing,<br>ref missing, ref missing, ref missing);</code>
</div>
<p>4.0中就可以直接写成: </p>
<div class="blockcode">
<em>复制内容到剪贴板</em>
<h5>代码:</h5>
<code id="code8">doc.SaveAs("Test.docx");</code>
</div>
<p>C#4.0对COM交互做了下面几方面的改进:<br><br> 1. Automatic object -&gt; dynamic mapping<br> 2. Optional and named parameters<br> 3. Indexed properties<br> 4. Optional “ref” modifier<br> 5. Interop type embedding (“No PIA”)<br><br>  对第1点和第5点的简单解释如下:<br><br>  在COM调用中,很多输入输出类型都是object,这样就必须知道返回对象的确切类型,强制转换后才可以调用相应的方法。在4.0中有了dynamic的支持,就可以在导入这些COM接口时将变量定义为dynamic而不是object,省掉了强制类型转换。<br><br>  PIA(Primary Interop Assemblies)是根据COM API生成的.Net Assembly,一般体积比较大。在4.0中运行时不需要PIA的存在,编译器会判断你的程序具体使用了哪一部分COM API,只把这部分用PIA包装,直接加入到你自己程序的Assembly里面。<br><br><span style="font-size: medium;"><strong>Co- and Contra-Variance</strong></span><br><br>  实在是不知道怎么<span class="t_tag">翻译</span>这两个词。<br><br>  在C#中,下面的类型转换是非法的: </p>
<div class="blockcode">
<em>复制内容到剪贴板</em>
<h5>代码:</h5>
<code id="code9">IList&lt;string&gt; strings = new List&lt;string&gt;();<br>IList&lt;object&gt; objects = strings;</code>
</div>
<p>因为你有可能会这样做,而编译器的静态检查无法查出错误: </p>
<div class="blockcode">
<em>复制内容到剪贴板</em>
<h5>代码:</h5>
<code id="code10">objects[0] = 5;<br>string s = strings[0];</code>
</div>
<p>4.0中在声明generic的Interface及Delegate时可以加in及out关键字,如: </p>
<div class="blockcode">
<em>复制内容到剪贴板</em>
<h5>代码:</h5>
<code id="code11">public interface IEnumerable&lt;out T&gt; : IEnumerable<br>{<br>IEnumerator&lt;T&gt; GetEnumerator();<br>}<br>public interface IEnumerator&lt;out T&gt; : IEnumerator<br>{<br>bool MoveNext();<br>T Current { get; }<br>}<br><br>public interface IComparer&lt;in T&gt;<br>{<br>public int Compare(T left, T right);<br>}</code>
</div>
<p>out关键字的意思是说IEnumerable&lt;T&gt;中T只会被用在输出中,值不会被改变。这样将IEnumerable&lt;string&gt;转为IEnumerable&lt;object&gt;类型就是安全的。<br><br>  in的意思正好相反,是说IComparer&lt;T&gt;中的T只会被用在输入中,这样就可以将IComparer&lt;object&gt;安全的转为IComparer&lt;string&gt;类型。<br><br>  前者被称为Co-Variance, 后者就是Contra-Variance。<br><br>  .Net4.0中使用out/in声明的Interface: </p>
<div class="blockcode">
<em>复制内容到剪贴板</em>
<h5>代码:</h5>
<code id="code12">System.Collections.Generic.IEnumerable&lt;out T&gt;<br>System.Collections.Generic.IEnumerator&lt;out T&gt;<br>System.Linq.IQueryable&lt;out T&gt;<br>System.Collections.Generic.IComparer&lt;in T&gt;<br>System.Collections.Generic.IEqualityComparer&lt;in T&gt;<br>System.IComparable&lt;in T&gt;</code>
</div>
<p>Delegate: </p>
<div class="blockcode">
<em>复制内容到剪贴板</em>
<h5>代码:</h5>
<code id="code13">System.Func&lt;in T, …, out R&gt;<br>System.Action&lt;in T, …&gt;<br>System.Predicate&lt;in T&gt;<br>System.Comparison&lt;in T&gt;<br>System.EventHandler&lt;in T&gt;</code>
</div>
<p><span style="font-size: medium;"><strong>Compiler as a Service</strong></span><br><br>  4.0中增加了与编译器相关的API,这样就可以将字符串作为代码动态编译执行,跟javascript好像。</p>

你可能感兴趣的:(新特性)