【转】 C#版本和.NET版本以及VS版本的对应关系
转自: http://blog.csdn.net/wulex/article/details/73499500
之所以在这里分享这个对应关系,是因为在C#基础知识系列的文章发布之后,有些初学者对.NET版本和C#语言特性之间的对应关系有点不清楚,有时候会弄混淆了。
并且通过这个对应关系,也可以帮助大家对C#和.NET 类库有个全面的把控,可以帮助大家理清楚C#和.NET 类库中各个知识点,使他们可以对号入坐。具体他们的之间对应关系见下表:
版本 | .NET Framework版本 | Visual Studio版本 | 发布日期 | 特性 |
---|---|---|---|---|
C# 1.0 | .NET Framework 1.0 | Visual Studio .NET 2002 | 2002.1 | 委托 |
事件 | ||||
C# 1.1 | .NET Framework 1.1 | Visual Studio .NET 2003 | 2003.4 | APM |
C# 2.0 | .NET Framework 2.0 | Visual Studio 2005(开始命名为Visual Studio) | 2005.11 | 泛型 |
匿名方法 | ||||
迭代器 | ||||
可空类型 | ||||
C# 3.0 | .NET Framework 3.0 | Visual Studio 2008 | 2007.11 | 隐式类型的部变量 |
.NET Framework 3.5 | 对象集合初始化 | |||
自动实现属性 | ||||
匿名类型 | ||||
扩展方法 | ||||
查询表达式 | ||||
Lambda表达式 | ||||
表达式树 | ||||
分部类和方法 | ||||
Linq | ||||
C# 4.0 | .NET Framework 4.0 | Visual Studio 2010 | 2010.4 | 动态绑定 |
命名和可选参数 | ||||
泛型的协变和逆变 | ||||
互操作性 | ||||
C# 5.0 | .NET Framework 4.5 | Visual Studio 2012 | 2012.8 | 异步和等待(async和await) |
调用方信息(Caller Information) |
C# 5.0中新增特性
C# 5.0随着VisualStudio 2012一起正式发布了,让我们来看看C#5.0中增加了哪些功能。
1. 异步编程
在.Net 4.5中,通过async和await两个关键字,引入了一种新的基于任务的异步编程模型(TAP)。在这种方式下,可以通过类似同步方式编写异步代码,极大简化了异步编程模型。如下式一个简单的实例:
static async void DownloadStringAsync2(Uri uri) { var webClient = new WebClient(); var result = await webClient.DownloadStringTaskAsync(uri); Console.WriteLine(result); }
而之前的方式是这样的:
static void DownloadStringAsync(Uri uri) { var webClient = new WebClient(); webClient.DownloadStringCompleted += (s, e) => { Console.WriteLine(e.Result); }; webClient.DownloadStringAsync(uri); }
也许前面这个例子不足以体现async和await带来的优越性,下面这个例子就明显多了:
public void CopyToAsyncTheHardWay(Stream source, Stream destination) { byte[] buffer = new byte[0x1000]; Action<IAsyncResult> readWriteLoop = null; readWriteLoop = iar => { for (bool isRead = (iar == null); ; isRead = !isRead) { switch (isRead) { case true: iar = source.BeginRead(buffer, 0, buffer.Length, readResult => { if (readResult.CompletedSynchronously) return; readWriteLoop(readResult); }, null); if (!iar.CompletedSynchronously) return; break; case false: int numRead = source.EndRead(iar); if (numRead == 0) { return; } iar = destination.BeginWrite(buffer, 0, numRead, writeResult => { if (writeResult.CompletedSynchronously) return; destination.EndWrite(writeResult); readWriteLoop(null); }, null); if (!iar.CompletedSynchronously) return; destination.EndWrite(iar); break; } } }; readWriteLoop(null); } public async Task CopyToAsync(Stream source, Stream destination) { byte[] buffer = new byte[0x1000]; int numRead; while ((numRead = await source.ReadAsync(buffer, 0, buffer.Length)) != 0) { await destination.WriteAsync(buffer, 0, numRead); } }
关于基于任务的异步编程模型需要介绍的地方还比较多,不是一两句能说完的,有空的话后面再专门写篇文章来详细介绍下。另外也可参看微软的官方网站:Visual Studio Asynchronous Programming,其官方文档Task-Based Asynchronous Pattern Overview介绍的非常详细, VisualStudio中自带的CSharp Language Specification中也有一些说明。
2. 调用方信息
很多时候,我们需要在运行过程中记录一些调测的日志信息,如下所示:
public void DoProcessing() { TraceMessage("Something happened."); }
为了调测方便,除了事件信息外,我们往往还需要知道发生该事件的代码位置以及调用栈信息。在C++中,我们可以通过定义一个宏,然后再宏中通过FILE和LINE来获取当前代码的位置,但C#并不支持宏,往往只能通过StackTrace来实现这一功能,但StackTrace却有不是很靠谱,常常获取不了我们所要的结果。
针对这个问题,在.Net 4.5中引入了三个Attribute:CallerMemberName
、CallerFilePath
和CallerLineNumber
。在编译器的配合下,分别可以获取到调用函数(准确讲应该是成员)名称,调用文件及调用行号。上面的TraceMessage函数可以实现如下:
public void TraceMessage(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) { Trace.WriteLine("message: " + message); Trace.WriteLine("member name: " + memberName); Trace.WriteLine("source file path: " + sourceFilePath); Trace.WriteLine("source line number: " + sourceLineNumber); }
另外,在构造函数,析构函数、属性等特殊的地方调用CallerMemberName属性所标记的函数时,获取的值有所不同,其取值如下表所示:
调用的地方 | CallerMemberName获取的结果 |
---|---|
方法、属性或事件 | 方法,属性或事件的名称 |
构造函数 | 字符串 “.ctor” |
静态构造函数 | 字符串 “.cctor” |
析构函数 | 该字符串 “Finalize” |
用户定义的运算符或转换 | 生成的名称成员,例如, “op_Addition”。 |
特性构造函数 | 特性所应用的成员的名称 |
例如,对于在属性中调用CallerMemberName
所标记的函数即可获取属性名称,通过这种方式可以简化 INotifyPropertyChanged 接口的实现。关于调用方信息更详细的资料,请参看MSDN:http://msdn.microsoft.com/zh-cn/library/hh534540.aspx。
C# 5.0五大新特性
第一:绑定运算符,:=:
这个只是简化了数据绑定,跟ASP.NET MVC3不断改进一样,其实不是什么亮点改进。
comboBox1.Text :=: textBox1.Text; //将文本框的内容绑定到下拉框。
第二:带参数的泛型构造函数:
这个的加入给一些设计增加了强大功能,泛型早在C#2.0加入后就有着强大的应用,一般稍微设计比较好的框架,都会用到泛型,c#5.0加入带参数泛型构造函数,则在原有基础上对C#泛型完善了很多。:)
public class T MyClass : T: class, new()
public class T MyClass : T:class, new(int)
第三:支持null类型运算:
此功能,个人觉得并非什么大的亮点,但至少对null类型,特别是有数据计算的这种null类型的支持,写代码还是方便不少。
注意对于Nullable Types,在C#2.0就加入进来了,但是不支持计算,比如:
int? x = null;
int? y = x + 40;
那么y值是多少?不支持计算,得到的是null,想必大家知道为什么结果是null了吧?但C#5.0可以,40加一个null的整数,我们要的结果是40,不过份吧?
int x? = null; int y? = x + 40; Myobject obj = null; Myotherobj obj2 = obj.MyProperty ??? new Myotherobj();
第四:case支持表达式:
这个是一个我很早就想如果能这样就好了,没想到在C#5.0里就加入此功能,以前case里只能写一个具体的常量,而现在可以加表达式了,灵活多了。
switch(myobj){ llorEmpty(myotherobj): //逻辑代码 case myotherobj.Trim().Lower: //逻辑代码 }
第五:扩展属性。
我们在C#3.0里有扩展方法,那么在C#5.0里将会加入扩展属性的感念,对照扩展方法,不难理解扩展属性的概念了。以下为扩展属性的定义举例:
[Associate(string)]
public static int Zivsoft_ExtensionProperty { get;set;}
C#5.0 远远不只是上面描述的5点新功能,它如同C#4.0加入dynamic概念一样,会加入异步处理概念,这个不是几行代码就能表达,而是将在设计,架构上,又会掀起一次飞跃……
为了大家抢先看,就给一段C#5.0一段简单的异步操作的代码例子,注意(C#5.0两个新加的关键字async, await):
Task<Movie> GetMovieAsync(string title); Task PlayMovieAsync(Movie movie); async void GetAndPlayMoviesAsync(string[] titles) { foreach (var title in titles) { var movie = await GetMovieAsync(title); await PlayMovieAsync(movie); } }