一:C#3.0新语言的特性

  • 自动属性(Auto-Implemented Properties)
  • 隐含类型局部变量(Local Variable Type Inference)
  • 匿名类型(Anonymous Types)
  • 对象与集合初始化器(Object and Collection Initializers)
  • 扩展方法(Extension Methods)
  • Lambda表达式和Lambda表达式树 (Lambda Expression and Lambda Expression Trees)

1.自动属性

自动属性可以避免原来这样我们手工声明一个私有成员变量以及编写get/set逻辑,在VS2008中可以像下面这样编写一个类,编译器会自动地生成私有变量和默认的get/set 操作。你也可以分别定义get和set的“protected”等访问级别。

2.隐含类型局部变量

C#3.0引进了var这个新关键字,在声明局部变量时可用于替代原先的类型名,即当一个变量声明标识为var类型并且该范围域中没有var名称类型存在,那么这个声明就称为隐含类型局部变量。

        隐含类型局部变量要点

  1. var为关键字,可以根据后面的初始化语句自动推断类型,这个类型为强类型。
  2. 初始化语句必须为表达式,不可以为空。且编译时可以推断类型。一旦初始化之后,只可以存储这种类型。
  3. var声明的仅限于局部变量,不可用于字段。亦可以用于for,foreach,using 等语句中。
  4. 数组也可以作为隐含类型。
  5. 初始化语句不能是一个自身的对象或者集合初始化器,但是他可以是包含一个对象或者初始化器的一个new表达式。
  6. 如果局部变量声明包含了多个声明符,其类型必须相同。

3.匿名类型

匿名类型允许定义行内类型,无须显式定义类型。常和var配合使用来声明匿名类型。

  1. var p1 = new { Id = 1, Name = "YJingLee", Age = 22 };//属性也不需要申明
  2. var p2 = new { Id = 2, Name = "XieQing", Age = 25 };
  3. p1 = p2;//p1,p2结构相同,可以互相赋值

在这里编译器会认为p1,p2相当于:

  1. public class SomeType
  2. {
  3. public int Id { get; set; }
  4. public string Name { get; set; }
  5. public int Age { get; set; }
  6. }

那么数组怎么定义呢?使用"new[]"关键字来声明数组,加上数组的初始值列表。像这样:

  1. var intArray = new[] { 2, 3, 5, 6 };
  2. var strArray = new[] { "Hello", "World" };
  3. var anonymousTypeArray = new[]
  4. {
  5. new { Name = "YJingLee", Age = 22 },
  6. new { Name = "XieQing", Age = 25 }
  7. };
  8. var a = intArray[0];
  9. var b = strArray[0];
  10. var c = anonymousTypeArray[1].Name;

匿名类型要点

  1. 可以使用new关键字调用匿名初始化器创建一个匿名类型的对象。
  2. 匿名类型直接继承自System. Object。
  3. 匿名类型的成员是编译器根据初始化器推断而来的一些读写属性。

4.对象与集合初始化器

对象初始化器 (Object Initializers) :

使得原来几行的属性赋值操作可以在一行完成。我们可以这样简化:像这样,对象初始化器由一系列成员对象组成,其对象必须初始化,用逗号间隔,使用{}封闭

  1. User user = new User { Id = 1, Name = "YJingLee", Age = 22 };

又例如,我把二个人加到一个基于泛型的类型为User的List集合中:

  1. List<User> user = new List<User>{
  2. new User{Id=1,Name="YJingLee",Age=22},
  3. new User{Id=2,Name="XieQing",Age=25},
  4. };

如果有相同名字和类型的两个对象初始化器将会产生相同的实例,可以相互赋值。例如:

  1. User user = new User { Id = 1, Name = "YJingLee", Age = 22 };
  2. User user2 = new User { Id = 2, Name = "XieQing", Age = 25 };
  3. user = user2;

除了在初始化类时设置简单的属性值外,对象初始化器特性也允许我们设置更复杂的嵌套(nested)属性类型。例如我们可以在上面定义的User类型同时拥有一个属于Address类型的叫“Address”的属性:

  1. User user = new User
  2. {
  3. Id = 1,
  4. Name = "YJingLee",
  5. Age = 22,
  6. Address = new Address
  7. {
  8. City = "NanJing",
  9. Zip = 21000
  10. }
  11. };

集合初始化器(Collection Initializers):

集合初始化器由一系列集合对象组成,用逗号间隔,使用{}封闭。
集合初始化器可以简化把几个对象一起添加到一个集合,编译器会自动为你做集合插入操作。例如我把七个数加到一个基于泛型的类型为int的List集合中

  1. List<int> num = new List<int> { 0, 1, 2, 6, 7, 8, 9 };

对象与集合初始化器要点

  1. 对象初始化器实际上利用了编译器对对象中对外可见的字段和属性进行按序赋值。
  2. 对象初始化器允许只给一部分属性赋值,包括internal访问级别
  3. 对象初始化器可以结合构造函数一起使用,并且构造函数初始化先于对象初始化器执行。
  4. 集合初始化器会对初始化器中的元素进行按序调用ICollection<T>.Add(T)方法。
  5. 注意对象初始化器和集合初始化器中成员的可见性和调用顺序。
  6. 对象与集合初始化器同样是一种编译时技术。

5.扩展方法

往往我们需要对CLR类型进行一些操作,但苦于无法扩展CLR类型的方法,只能创建一些helper方法,或者继承类。我们来修改上面的User类:

  1. public class User
  2. {
  3. public int Id { get; set; }
  4. public string Name { get; set; }
  5. public int Age { get; set; }
  6. public string Read()
  7. {
  8. return "Id:" + Id + "姓名:" + Name + "年龄:" + Age;
  9. }

然后调用:

  1. var user = new { Id = 1, Name = "YJingLee", Age = 22 };
  2. var str = user.Read();

现在有了扩展方法就方便多了。

扩展方法允许开发人员往一个现有的CLR类型的公开契约(contract)中添加新的方法,而不用生成子类或者重新编译原来的类型。扩展方法有助于把今天动态语言中流行的对duck typing的支持之灵活性,与强类型语言之性能和编译时验证融合起来。

扩展方法是可以通过使用实例方法语法调用的静态方法。效果上,使得附加的方法扩展已存在类型和构造类型成为可能。他可以对现有类功能进行扩充,从而使该类型的实例具有更多的方法(功能)。
扩展方法允许我们在不改变源代码的情况下扩展(即添加不能修改)现有类型中的实例方法。

扩展方法给我们一个怎样的思路呢?我们一步一步做一下!
首先声明扩展方法:通过指定关键字this修饰方法的第一个参数。注意扩展方法仅可声明在静态类中。扩展方法具备所有常规静态方法的所有能力,可以使用实例方法语法来调用。接着就可以调用扩展方法了。下面通过一个具体的实例分析一下:
例如我们要检查一个字符串变量是否是合法的电子邮件地址?在.Net2.0框架下像这样:

  1. var email = "leeyongjing@gmail.com";
  2. if (EmailValidator.IsValid(email))
  3. {
  4. Response.Write("YJingLee提示:这是一个正确的邮件地址");
  5. }

而使用扩展方法的话,我可以添加“IsValidEmailAddress()”方法到string类本身中去,该方法返回当前字符串实例是否是个合法的字符串。

  1. if (email.IsValidEmailAddress())
  2. {
  3. Response.Write("YJingLee提示:这是一个正确的邮件地址");
  4. }

我们是怎么把这个IsValidEmailAddress()方法添加到现有的string类里去的呢?先定义一个静态类,再定义“IsValidEmailAddress”这个静态的法来实现的。

  1. public static class Extensions//静态类
  2. {
  3. public static bool IsValidEmailAddress(this string s)
  4. //静态方法和this
  5. {
  6. Regex regex = new Regex(@"^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$");
  7. return regex.IsMatch(s);
  8. }
  9. }

注意,上面的静态方法在第一个类型是string的参数变量前有个“this”关键词,这告诉编译器,这个特定的扩展方法应该添加到类型为 “string”的对象中去。然后在IsValidEmailAddress()方法实现里,我可以访问调用该方法的实际string实例的所有公开属性 /方法/事件,取决于它是否是合法电子邮件地址来返回true/false。

扩展方法不仅能够应用到个别类型上,也能应用到.NET框架中任何基类或接口上。即可用于整个.NET框架丰富的可组合的框架层扩展。

扩展方法要点

    1. 扩展方法的本质为将实例方法调用在编译期改变为静态类中的静态方法调用。事实上,它确实拥有静态方法所具有的所有功能。
    2. 扩展方法的作用域是整个namespace可见的,并且可以通过using namespace来导入其它命名空间中的扩展方法。
    3. 扩展方法的优先级:现有实例方法优先级最高,其次为最近的namespace下的静态类的静态方法,最后为较远的namespace下的静态类的静态方法。
    4. 扩展方法是一种编译时技术,注意与反射等运行时技术进行区别,并慎重使用。

6.Lambda表达式和Lambda表达式树

Lambda表达式

我们从“所有字符串查找包含YJingLee子字符串”说起。在C# 2.0中,匿名方法允许我们以内联的方式来实现委托实例,它提供强大的函数式编程语言,但是标记显得相当的冗长和带有强制性。我们使用C# 2.0 中的匿名方法查找,代码如下:

  1. var inString = list.FindAll(delegate(string s)
  2. { return s.Indexof("YJingLee") >= 0; });

现在可以使用C# 3.0带来的Lambda表达式允许我们使用一种更接近人的思维、更自然的方式来实现类似于匿名方法同样的效果,看下面的代码多么简洁:

  1. var inString = list.FindAll(s => s.Indexof("YJingLee") >= 0);

Lambda表达式格式:(参数列表)=>表达式或语句块
具体意义:定义Lambda接受参数列表,运行表达式或语句块返回表达式或语句块的值传给这个参数列表。

Lambda表达式参数类型可以是隐式类型或显式类型。在显式列表中,每个参数的类型是显式指定的,在隐式列表中,参数的类型由Lambda表达式出现的语境自动推断类型。
Lambda表达式的参数列表可以有一个或多个参数,或者无参数。在有单一的隐型参数的lambda表达式中,圆括号可以从参数列表中省略。
例如:

  1. (x, y) => x * y;//多参数,隐式类型=>表达式
  2. x => x * 10;//单参数,隐式类型=>表达式
  3. x => { return x * 10; }; //单参数,隐式类型=>语句块
  4. (int x) => x * 10;//单参数,显式类型=>表达式
  5. (int x) => { return x * 10; };//单参数,显式类型=>语句块
  6. () => Console.WriteLine(); //无参数

下面看这个例子:
  
我们写了一个User类及增加了2个人,接下来,我们使用由LINQ提供的新的Where和Average方法来返回集合中的人的一个子集,以及计算这个集合中的人的平均年龄:

  1. List<User> user = new List<User>{
  2. new User{Id=1,Name="YJingLee",Age=22},
  3. new User{Id=2,Name="XieQing",Age=25},
  4. };
  5. //获取特定人时所用的过滤条件,p参数属于User类型
  6. var results = user.Where(p => p.Name == "YJingLee").ToList();
  7. //用User对象的Age值计算平均年龄
  8. var average = user.Average(p => p.Age);

对这个Lambda表达式做个简要分析:

  1. var resultsdelegate = user.Where(delegate(User p)
  2. {
  3. return p.Name == "YJingLee";// 返回一个布尔值
  4. });
  5. var averagedelegate = user.Average(delegate(User p)
  6. {
  7. return p.Age;
  8. });

Lambda表达式L可以被转换为委托类型D,需要满足以下条件:
  
L的参数类型要与D的参数个数相等,类型相同,返回类型相同,无论是表达式,还是语句块。注意隐式类型要参与类型辨析。

Lambda表达式树

Lambda表达式树允许我们像处理数据(比如读取,修改)一样来处理Lambda表达式。我以一个例子简单说明:

  1. Expression<Func<int, bool>> filter = n => (n * 3) < 5;
  2. BinaryExpression lt = (BinaryExpression)filter.Body;
  3. BinaryExpression mult = (BinaryExpression)lt.Left;
  4. ParameterExpression en = (ParameterExpression)mult.Left;
  5. ConstantExpression three = (ConstantExpression)mult.Right;
  6. ConstantExpression five = (ConstantExpression)lt.Right;
  7. var One = filter.Compile();
  8. Console.WriteLine("Result: {0},{1}", One(5), One(1));
  9. Console.WriteLine("({0} ({1} {2} {3}) {4})", lt.NodeType,
  10. mult.NodeType, en.Name, three.Value, five.Value);

Lambda表达式和Lambda表达式树要点

  1. Lambda表达式的参数类型可以忽略,因为可以根据使用的上下文进行推断。
  2. Lambda表达式的主体(body)可以是表达式,也可以是语句块。
  3. Lambda表达式传入的实参将参与类型推断,以及方法重载辨析。
  4. Lambda表达式和表达式体可以被转换为表达式树。
  5. 表达式树允许lambda表达式能够代表数据结构替代表示为执行代码。

好了,我在这里简单的把C# 3.0新语言特性和改进说了一下,接下来,正式进入这个系列的主题部分——LINQ。

LINQ学习之旅 C#3.0新特性(一)的更多相关文章

  1. Javaweb学习笔记——(七)——————myexlipse基本使用、jdk5.0新特性及反射讲解

    1.debug调试模式: *使用这种模式,调试程序(看到程序运行停止在这一行) -显示出来行号 -双击左边,出现一个圆点,表示设置了一个断点 *使用debug as方式,运行程序 -特使是否进入到调试 ...

  2. JavaSE 学习笔记之Jdk5.0新特性(十九)

    Jdk5.0新特性: Collection在jdk1.5以后,有了一个父接口Iterable,这个接口的出现的将iterator方法进行抽取,提高了扩展性. --------------------- ...

  3. c# 6.0新特性(二)

    写在前面 上篇文章介绍了c#6.0的using static,Auto Property Initializers,Index Initializers新的特性,这篇文章将把剩下的几个学习一下. 原文 ...

  4. c# 6.0新特性(一)

    写在前面 接近年底了,基本上没什么活了,就学点新东西,就想着了解下c# 6.0的新特性.在code project上看到了一篇不错的文章,就准备翻译一下,顺便照着学习学习.废话不多说,直奔主题. 原文 ...

  5. 浅谈Tuple之C#4.0新特性那些事儿你还记得多少?

    来源:微信公众号CodeL 今天给大家分享的内容基于前几天收到的一条留言信息,留言内容是这样的: 看了这位网友的留言相信有不少刚接触开发的童鞋们也会有同样的困惑,除了用新建类作为桥梁之外还有什么好的办 ...

  6. 返璞归真 asp.net mvc (13) - asp.net mvc 5.0 新特性

    [索引页][源码下载] 返璞归真 asp.net mvc (13) - asp.net mvc 5.0 新特性 作者:webabcd 介绍asp.net mvc 之 asp.net mvc 5.0 新 ...

  7. 精进不休 .NET 4.5 (12) - ADO.NET Entity Framework 6.0 新特性, WCF Data Services 5.6 新特性

    [索引页][源码下载] 精进不休 .NET 4.5 (12) - ADO.NET Entity Framework 6.0 新特性, WCF Data Services 5.6 新特性 作者:weba ...

  8. 返璞归真 asp.net mvc (7) - asp.net mvc 3.0 新特性之 Controller

    原文:返璞归真 asp.net mvc (7) - asp.net mvc 3.0 新特性之 Controller [索引页][源码下载] 返璞归真 asp.net mvc (7) - asp.net ...

  9. 返璞归真 asp.net mvc (8) - asp.net mvc 3.0 新特性之 Model

    原文:返璞归真 asp.net mvc (8) - asp.net mvc 3.0 新特性之 Model [索引页][源码下载] 返璞归真 asp.net mvc (8) - asp.net mvc ...

随机推荐

  1. 运用Zabbix实现内网服务器状态及局域网状况监控(1) —— Zabbix介绍

    一.Zabbix简介 Zabbix 是一个企业级的.开源的.分布式的监控套件 Zabbix 可以监控网络和服务的监控状况. Zabbix 利用灵活的告警机制,允许用户对事件发送基于 Email 的告警 ...

  2. Hystrix介绍以及服务的降级限流熔断

    (dubbo熔断,Hystrix问的少) 无论是缓存层还是存储层都会有出错的概率,可以将它们视同为资源.作为并发量较大的系统,假如有一个资源不可用,可能会造成线程全部 hang (挂起)在这个资源上, ...

  3. SQL语句(一)SQL和数据库数据表的创建

    SQL的组成 (1) 数据定义语言DDL(Data Definition Language) 用于数据库和数据表的创建.修改和删除等操作 CREATE (create) 创建数据库.数据表 ALTER ...

  4. python 内建函数专题

    all 用来控制 import , 甚至可以改变 _private 为 public enter , exit 用于上下文管理器 iter 用于迭代器 repr 给计算机读, str ==> s ...

  5. Python排序算法之选择排序

    选择排序 选择排序比较好理解,好像是在一堆大小不一的球中进行选择(以从小到大,先选最小球为例): 1. 选择一个基准球 2. 将基准球和余下的球进行一一比较,如果比基准球小,则进行交换 3. 第一轮过 ...

  6. PHP 将amr音频文件转换为mp3格式

    说下整体思路 1.服务器安装ffmpeg 2.使用ffmpeg -i 指令来转换amr为mp3格式(这个到时候写在PHP代码中,使用exec函数执行即可) 3.在网页端使用HTML5的audio标签来 ...

  7. Redis详解(一)冰叔带你了解Redis

       Redis 是一种基于 键值对 的 NoSQL 数据库.与很多键值对数据库不同,Redis 提供了丰富的 值数据存储结构,包括 string(字符串).hash(哈希).list(列表).set ...

  8. luogu 1030 求先序遍历

    此题给出中序遍历和后序遍历后的序列,乍一看确乎想不出法子解决,毕竟是逆向思维: 但是后序遍历的特殊性质 son1,son2,x 使得后序的末尾便是根节点,再由中序天然的递归性质便可递归输出,用下fin ...

  9. 20155215 2016-2017-2 《Java程序设计》第9周学习总结

    20155215 2016-2017-2 <Java程序设计>第9周学习总结 教材学习内容总结 第十六章 JDBC入门 - JDBC(Java DataBase Connectivity) ...

  10. Linux - 网络检测

    linux 利用bmon/nload/iftop/vnstat/iptraf实时查看网络带宽状况 .添加yum源方便安装bmon # rpm -Uhv http://apt.sw.be/redhat/ ...