C# 的10 年
看着一个编程语言的诞生,然后逐步追随其成长,是一件相当有趣的事,特别是该编程语言一直都处于主流语言的时候,很可惜的,这种机会并不常有,C#是在我编程生涯中,唯一一个从其出生即跟随至今的编程语言。
在C#诞生之初,也是Anders Hejlsberg离开Borland之后的数年后,对于一个老Delphi设计师而言,对于C#的感情因素远比其语言本质来得重,Anders是Delphi的主要掌舵者,他成功的将Delphi带入一个RAD工具前所未进过的殿堂,在他离开Borland而建立C#后,我们在C#上看到了Delphi的影子,PME的设计,Refection的进化,诸多设计都可见到Delphi的背影。当然,我并不是说C#是抄袭Delphi,毕竟当时也有人说C#与Java很像,C#与C++很像,这些其实都不重要,重要的是,C#是撷取了许多语言的优点而成的,对于程序设计师而言,这点就足够了。
C# 1.0随着.NET Framework一起问市,创始者Anders将C# 1.0定位为Managed Version,这是继Java之后的一个中继平台高阶语言,与Java相同,.NET Framework中的CLR负责来执行由C# 编译器所产生的IL Code,借此将机器语言及中介语言切开,如你所见,优点是C#可以与VB.NET互通,在理论上,还能针对不同的CPU进行最佳化,这是传统直接编译成机器码的编译器所得不到的好处。
C# 2.0进入了泛型(Generic)时代,在这个版本中,程序设计师可以仅写一个Stack<T>,然后支持所有类型,而不用受object原型的拖累,泛型的优点在于其一开始就已定型,因此假设将一变量声明为Stack<int>,那么之后就不能够将string元素填入,既可脱开单一类型必须撰写对应支持的Stack负担,还得到了使用object所得不到的编译时期验证。
C# 3.0开始,进入了一个极少数编程语言到过的境界,Anders大胆的于C#中加入了LINQ(Language Integrated Query),将查询语句硬是摆进了编程语言中,事实证明LINQ是个相当棒的发明。
C# 4.0,一个崭新的时代,Anders再次显露了其大胆的个性,将原本受尽众人诟病的Un-Type Programming带入了C#,让原本以Typed Programming挂帅的C#,顿时多了另一个Dynamic Language的称号,虽然!人们对于Un-Type Programming的疑虑仍未解除,但Dynamic Language机制的加入,无疑的开启了C#另一条进步的路。
10年,对于一个编程语言来说,并不是一段很长的时间,C#于这10年间的转变算是相当的快速,且每次的转变,都会让人觉得有疑虑,可是最后都会不禁对其大胆的尝试感到赞赏,当然!前提是你得是实务挂帅的人,因为只要从理论上及原则上来看,由C# 3.0开始,其轴心思想即不在旧有编程语言抱持的一贯原则上了,而是在如何加快设计师的生产力上。
严谨(Typed Programming) VS 松散(Dynamic Programming) 或者说 强类型(Typed Programming) VS 若类型(Dynamic Programming)
在C# 3.0之前,她是一个严谨的编程语言,也可称为是Typed Programming,意思是,当你将一个变数声明为int,那么你就不能把一个字串赋值给它,这样的做法有很多好处,其中之一就是编译器会于编译时期即告知设计者所犯下的类型错误,这大幅的减少了因类型错误而产生的BUG,同时间接的养成了C#设计师对于类型的敏感度。
从C# 3.0开始,因为LINQ的加入,var关键字出现了,其出现的原因是LINQ运算式的回传值,常常是设计师难以快速推估出来的,以下面的例子来说吧:
static void Main(string[] args)
{
List<Person> list = new List<Person>() {
new Person(){ID="001",Name="code6421",Age = 18},
new Person(){ID="002",Name="tom",Age = 18},
new Person(){ID="003",Name="mary",Age = 18}};
List<Addresses> alist = new List<Addresses>()
{
new Addresses(){ID="001",Address="Taipen"},
new Addresses(){ID="002",Address="Tainan"},
new Addresses(){ID="003",Address="US"}
};
var result = from s1 in list
join s2 in alist on s1.ID equals s2.ID into p
select new { Name = s1.Name, Addresses = p };
foreach (var item in result)
{
Console.WriteLine(item.Name);
Console.WriteLine("-----------------");
foreach (var addr in item.Addresses)
Console.WriteLine(addr.Address);
Console.WriteLine("-----------------");
}
Console.ReadLine();
}
如果没有var,那么就得写成下面这样:
1 static void Main(string[] args) 2 { 3 List<Person> list = new List<Person>() { 4 new Person(){ID="001",Name="code6421",Age = 18}, 5 new Person(){ID="002",Name="tom",Age = 18}, 6 new Person(){ID="003",Name="mary",Age = 18}}; 7 8 List<Addresses> alist = new List<Addresses>() 9 { 10 new Addresses(){ID="001",Address="Taipen"}, 11 new Addresses(){ID="002",Address="Tainan"}, 12 new Addresses(){ID="003",Address="US"} 13 }; 14 15 IEnumerable<PersonJoinResult> result = from s1 in list 16 join s2 in alist on s1.ID equals s2.ID into p 17 select new PersonJoinResult{ Name = s1.Name, Addresses = p }; 18 foreach (PersonJoinResult item in result) 19 { 20 Console.WriteLine(item.Name); 21 Console.WriteLine("-----------------"); 22 foreach (Addresses addr in item.Addresses) 23 Console.WriteLine(addr.Address); 24 Console.WriteLine("-----------------"); 25 } 26 Console.ReadLine(); 27 } 28 } 29 30 public class PersonJoinResult 31 { 32 public string Name { get; set; } 33 public IEnumerable<Addresses> Addresses { get; set; } 34 }
很明显的,即使var背负上不定类型的臭名,但其对于代码的简化有着莫大的帮助,更何况,var于右赋值完成时,即转变为具体类型,因此精确的说,var还是具型(强类型)的设计。
C#于4.0中添加了一个新成员:dynamic,与var这种乍看不具型但实际具型的设计不同,dynamic是完全不具型的设计,它的类型是执行时期时决定的,所以下面的例子是可以通过编译的。
class Program { static void Main(string[] args) { dynamic p = new Person(); p.Hello(); } } public class Person { public string ID { get; set; } public string Name { get; set; } public int Age { get; set; } }
Person并没有一个方法称为Hello,原本于Typed Programming的原则下,这个程序是无法通过编译的,但C# 4.0的dynamic型别却可以让这段程序通过编译,将一变量宣告为dynamic型别,即是告诉编译器【我知道我在做什么,你别管了!】。
有趣的还有下面这段代码。
static void Main(string[] args) { dynamic p = 15; Console.WriteLine(p); }
此时p的类型是什么呢?答案是object,事实上当你将某一变量宣告为dynamic时,C#编译器就会把它视为是object,然后以Lambda Expression的方式来处理你对此变量的调用、属性存取、Index存取等等,即使我们明确的知道p应该是Integer,但由于已经标为dynamic,自然的也就不能再经由具型来处理了。这个例子告诉我们,dynamic没那么聪明,不会因为你设了一个简单值给他,编译器便会很聪明的使用具型方式处理,一切还是循不具型方式来。因此,如非必要,否则别把原本可具型的东西宣告为dynamic,那对程式的效能及可读性是莫大的伤害。但也不必因此而不用它,毕竟利刃是给会用的人使用的。
var 與 dynamic (未完待续...)
转自 : http://h2appy.blog.51cto.com/609721/743662/
部分词语有替换,以便符合使用简体中文的人的习惯:
程序设计师
程式--编程
支援--支持
型别--类型
变数--变量
宣告--声明
世代--时代
函式呼叫--调用