C# 40中的新功能.docx
《C# 40中的新功能.docx》由会员分享,可在线阅读,更多相关《C# 40中的新功能.docx(26页珍藏版)》请在冰豆网上搜索。
![C# 40中的新功能.docx](https://file1.bdocx.com/fileroot1/2023-1/1/4c4b7346-d81b-4965-bd25-a0de621a0ab2/4c4b7346-d81b-4965-bd25-a0de621a0ab21.gif)
C#40中的新功能
VS2010和.NET4.0系列之《C#4中的可缺省参数和具名实参(以及ASP.NETMVC2中的一个很酷的场景)》篇
By SAUCER | Published:
2010年09月29日
【原文地址】 OptionalParametersandNamedArgumentsinC#4(andacoolscenariow/ASP.NETMVC2)
【原文发表日期】Friday,April02,20101:
28AM
【除了写博客外,我现在还使用Twitter发短贴和共享链接。
请通过
这是我针对即将发布的VS2010和.NET4所撰写的 贴子系列的第十七篇。
今天的贴子讨论新加到C#4.0中的2个语言特性:
可缺省参数(optionalparameters)和具名实参(namedarguments),以及在ASP.NETMVC2(VB和C#)中一种利用可缺省参数的很酷的方式。
C#4.0中的可缺省参数
C#4.0现在对方法,构造器,以及索引器支持使用可缺省的参数(注:
VB支持可缺省参数可是有年头了)。
当参数的默认值作为声明的一部分被指定的时候,参数就是可缺省的。
例如,下面这个方法接受2个参数,一个“category”字符串参数,另一个“pageIndex”整数参数。
“pageIndex”参数有一个默认值0,它因此是一个可缺省的参数:
当调用上面的方法时,我们可以显式地传递2个参数给它:
或者我们可以省略掉传递第二个参数,在这样的情形下,其默认值0就会被传进去:
注意,VS2010的Intellisense在显示语句完成时,会表示哪个参数是可缺省的,以及它的默认值:
C#4.0中的具名实参和可缺省参数
C#4.0现在还支持“具名实参”的概念。
这允许你把传给一个方法的参数显式地命名,而不是通过实参的位置来识别它。
例如:
我可以编写下面这样的代码,通过其名称来识别传给GetProductsByCategory方法的第二个参数(将其用法变得更为明确一点):
当一个方法支持多个可缺省参数,而你想要指定在传递哪个实参时,具名实参会非常有用。
例如,下面我们有一个DoSomething方法,其接受2个可缺省参数:
我们可以使用具名实参,以下面任何一种方式来调用上面这个方法:
因为2个参数都是可缺省的,在只有1个(或者0个)参数被指定的情形下,那个没被指定的参数的默认值就会被传进去。
ASP.NETMVC2和可缺省参数
有一个非常棒的使用场景,我们可以在其中利用VB和C#中可缺省参数支持,那就是ASP.NETMVC2中控制器类上的Action方法的输入绑定支持。
例如,考虑一个我们想要把“Products/Browse/Beverages”或“Products/Browse/Deserts”这样的URL映射到一个控制器action方法的场景。
我们可以编写一个URL导向规则,将URL映射到一个方法上,象这样:
然后,我们可以选择使用一个“page”查询字符串值来表示由Browse方法显示的结果是否应该是分页的,如果是分页的,应该显示结果的哪一页。
例如,/Products/Browse/Beverages?
page=2。
在ASP.NETMVC1中,你一般这样处理,在action方法上添加一个“page”参数,将其设置为 nullableint (意味着如果“page”查询字符串值不存在的话,其值就是null)。
然后你可以编写象下面这样的代码,将 nullableint 转换成一个 int,如果查询字符串中不存在值的话,就赋予一个默认值:
在ASP.NETMVC2中,你现在可以利用VB和C#中的可缺省参数支持,来更简明,更清晰地表达这个行为。
只要将action方法的参数声明为带默认值的可缺省参数即可:
C#
VB
如果查询字符串有“page”值的话(例如/Products/Browse/Beverages?
page=22),它就会以一个整数传给该action方法。
如果查询字符串没有“page”值的话(
例如/Products/Browse/Beverages),默认值0就会被传给该action方法。
这使得代码更加简明,可读性也提高了。
结语
VS2010中的C#和VB带有一堆很棒的新语言特性。
上述2个特性(可缺省参数和具名实参)是其中2个而已,在以后我还会在博客中讨论更多其他的新特性。
如果你在寻找一本总结了C#中所有语言特性(包括C#4.0中的),以及对核心.NET类库有很好的概述的好书的话,你也许应该查阅一下O’Reilly出版社新出版的《C#4.0inaNutshell》一书:
精进不休.NET4.0(4)-C#4.0新特性之命名参数和可选参数,动态绑定(dynamic),泛型协变和逆变,CountdownEvent,Barrier
作者:
webabcd
介绍
C#4.0的新特性
∙NamedAndOptionalArguments-命名参数和可选参数
∙DynamicBinding-动态绑定(dynamic用于动态编程,其依赖于DynamicLanguageRuntime)
∙Covariance-泛型的协变
∙Contravariance-泛型的逆变
∙CountdownEvent-线程、任务同步类。
线程或任务一直阻塞到CountdownEvent的计数为0为止
∙Barrier-线程、任务同步类。
其用来同步一个线程组或任务组中所有的线程或任务,先到达的线程或任务在此阻塞
示例
1、 命名参数和可选参数的Demo
NamedAndOptionalArguments.aspx.cs
/*
*命名参数和可选参数
*命名参数:
调用方法时,可以不按位置传递参数,而是指定参数的命名来传值
*可选参数:
声明方法中的参数时,可以为其设置默认值,那么在调用该方法时,这种可选参数是可以忽略的
*/
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Web;
usingSystem.Web.UI;
usingSystem.Web.UI.WebControls;
namespaceCSharp
{
public partial class NamedAndOptionalArguments:
System.Web.UI.Page
{
voidPage_Load()voidPage_Load(objectsender,EventArgse)
{
Write("hello");
Write("hello", "webabcd");
Write("hello",p3:
false,p2:
"webabcd");
}
voidWrite()voidWrite(string p1, string p2= "p2",boolp3= true)
{
Response.Write(string.Format("p1:
{0};p2:
{1};p3:
{2}",p1,p2,p3.ToString()));
Response.Write("
");
}
}
}
/*
运行结果:
p1:
hello;p2:
p2;p3:
True
p1:
hello;p2:
webabcd;p3:
True
p1:
hello;p2:
webabcd;p3:
False
*/
2、dynamic的Demo
DynamicBinding.aspx.cs
/*
*dynamic-用于动态编程,其依赖于DynamicLanguageRuntime(DLR)
*
*/
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Web;
usingSystem.Web.UI;
usingSystem.Web.UI.WebControls;
namespaceCSharp
{
public class DyanmicDemo
{
string Hello() string Hello(string name)
{
return "hello:
" +name;
}
public string Name{ get; set;}
public string this[string value]
{
get
{
returnvalue;
}
}
dynamicGetNames()dynamicGetNames()
{
Listnames= new List(){ "web", "webabc", "webabcd" };
returnnames;
}
}
public partial class DynamicBinding:
System.Web.UI.Page
{
voidPage_Load()voidPage_Load(objectsender,EventArgse)
{
dynamicd= new DyanmicDemo();
Response.Write(d.Hello("method"));
Response.Write("
");
d.Name= "hello:
property";
Response.Write(d.Name);
Response.Write("
");
Response.Write(d["hello:
indexer"]);
Response.Write("
");
Response.Write(d.GetNames().Count.ToString());
//注意:
下面这句会报错,因为不支持扩展方法
//Response.Write(d.GetNames().Last());
}
}
}
/*
运行结果:
hello:
method
hello:
property
hello:
indexer
3
*/
3、泛型的协变的Demo
Covariance.aspx.cs
/*
泛型协变规则:
泛型参数受out关键字约束,隐式转换目标的泛型参数类型必须是当前类型的“基类”
*/
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Web;
usingSystem.Web.UI;
usingSystem.Web.UI.WebControls;
namespaceCSharp
{
public partial class Covariance:
System.Web.UI.Page
{
voidPage_Load()voidPage_Load(objectsender,EventArgse)
{
Listhuman= new List();
human.Add(new Human{Name= "aaa" });
human.Add(new Human{Name= "bbb" });
human.Add(new Human{Name= "ccc" });
Listhero= new List();
hero.Add(new Hero{Name= "ddd",Story= "尿床" });
hero.Add(new Hero{Name= "eee",Story= "撒谎" });
hero.Add(new Hero{Name= "fff",Story= "打架" });
/*
*List实现了如下接口IEnumerable,所以可以实现协变
* public interfaceIEnumerable:
IEnumerable
*{
* //Summary:
* // Returnsanenumeratorthatiteratesthroughthecollection.
* //
* //Returns:
* // ASystem.Collections.Generic.IEnumeratorthatcanbeused to iteratethrough
* // thecollection.
* IEnumeratorGetEnumerator();
*}
*/
//Hero的基类是Human,所以Hero可以协变到Human,所以下面的表达式成立
Listlist=human.Union(hero).ToList();
foreach(Humanh in list)
{
Response.Write(h.Name);
Response.Write("
");
}
}
class Human
{
public string Name{ get; set;}
}
class Hero:
Human
{
public string Story{ get; set;}
}
}
}
/*
运行结果:
aaa
bbb
ccc
ddd
eee
fff
*/
4、泛型的逆变的Demo
Contravariance.aspx.cs
/*
泛型逆变规则:
泛型参数受 in 关键字约束,隐式转换目标的泛型参数类型必须是当前类型的“子类”
*/
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Web;
usingSystem.Web.UI;
usingSystem.Web.UI.WebControls;
namespaceCSharp
{
public partial class Contravariance:
System.Web.UI.Page
{
voidPage_Load()voidPage_Load(objectsender,EventArgse)
{
IOutputhuman= new Output();
//因为IOutput,并且Human的子类是Hero,所以IOutput可以逆变到IOutput
IOutputhero=human;
hero.Write(new Hero{Name= "webabcd" });
}
interfaceIOutput
{
voidWrite(To);
}
class Output:
IOutput
whereT:
Human
{
voidWrite()voidWrite(To)
{
HttpContext.Current.Response.Write(o.Name);
}
}
class Human
{
public string Name{ get; set;}
}
class Hero:
Human
{
public string Story{ get; set;}
}
}
}
/*
运行结果:
webabcd
*/
5、CountdownEvent的Demo
CountdownEventDemo.aspx.cs
/*
*CountdownEvent-线程、任务同步类。
线程或任务一直阻塞到CountdownEvent的计数为0为止
*1、当有新的需要同步的线程或任务产生时,就调用AddCount增加CountdownEvent的计数
*2、当有线程或任务到达同步点时,就调用Signal函数减小CountdownEvent的计数
*3、当CountdownEvent的计数为0时,就表示所有需要同步的任务已经完成。
通过Wait来阻塞线程
*/
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Web;
usi