C# 3.0 版和 Visual Studio 2008 一起发布于 2007 年下半年,但完整的语言功能是在 .NET Framework 3.5 版中发布的。 此版本标示着 C# 发展过程中的重大更改。 C# 成为了真正强大的编程语言。

一、隐式类型var

从 Visual C# 3.0 开始,在方法范围中声明的变量可以具有隐式类型var。隐式类型可以替代任何类型,编译器自动推断类型。

1、var类型的局部变量必须赋予初始值,包括匿名类(初始值不能为null)。

  1. var s = c#”;
  2. var name = new {name=”aa”,age=24};

2、隐式类型的数组

  1. var a = new[]{100};//int[] a=new int[]{1,10,100}
  2. var b = new[]{new[]{1,2,3},new[] {4,5,6}}//交错数组也可用new[]初始化,不支持隐式类型的多位数组。

3、var 只能作为局部变量使用,即只能定义在方法内或在属性get、set访问器中。还可用于foreach ,for , using语句中。

  1. public string Name
  2. {
  3. get
  4. {
  5. var p = new Person();//正确
  6. return p.Name;
  7. }
  8. }
  1. for(var i=0;i<10,i++)
  2. {}
  3.  
  4. using (var file=new StreamReader(“”)
  5. {}

4、var 多数情况在匿名类型和LINQ中使用。

  1. string[] words = { "aa", "bb", "cc" };
  2. var upperLower = from w in words
  3. select new { Upper = w.ToUpper(), Lower = w.ToLower() };
  4. foreach (var word in upperLower)
  5. {
  6. Console.WriteLine(word.Upper+","+ word.Lower);
  7. }

二、扩展方法

使您能够向现有类型“添加”方法,而无需创建新的派生类型。

1、最常见的扩展方法是LINQ标准查询运算符。

扩展方法向IEnumerable和IEnumerable类型添加查询功能。

  1. int[] ints={10,45,15,39};
  2. var result=ints.OrderBy(g=>g);//扩展方法是一种特殊的静态方法,但可像扩展类型上的实例方法一样进行调用。
  3. foreach(var i in result)
  4. {
  5. Console.Write(i);
  6. }

2、对已有的类型进行扩展。

所有的扩展方法写在一个静态类中,相当于存放扩展方法的容器。

所有的扩展方法为静态方法。

扩展方法的第一个参数this后跟着的类表示要扩展的类型。扩展方法第一个参数后才是真正的参数列表。

  1. void Main()
  2. {
  3. string s = "Hello Extension";
  4. int i = s.WordCount();
  5. Console.WriteLine(i.ToString());
  6. }
  7.  
  8. public static class MyExtensions //所有的扩展方法写在一个静态类中,相当于存放扩展方法的容器。
  9. {
  10. public static int WordCount(this String str)//this String表示要扩展的类型。扩展方法第一个参数后才是真正的参数列表
  11. {
  12. return str.Split(new char[] { ' ', '?' }, StringSplitOptions.RemoveEmptyEntries).Length;
  13. }
  14. }

三、自动实现的属性

当属性访问器中不需要其他逻辑时,自动实现的属性声明更为简洁。

1、自动实现的属性必须同时声明get和set访问器。

  1. public int One{get;set;}

2、使用private set设置只读的自动属性,在定义此属性的类本身中还是可以初始化赋值的。

  1. public string Name{get;private set;}

3、自动实现的属性不允许具有Attribute属性。

四、对象/集合初始值设定项

1、对象初始值设定项

可以在创建对象时向对象的可访问字段或属性赋值,而无需显示调用构造函数。从 C# 6 开始,除了分配字段和属性外,对象初始值设定项还可以设置索引器。

例1:简单应用

  1. public class Cat
  2. {
  3. public string name { set; get; }
  4. public int age { get; set; }
  5. }
  6.  
  7. void Main()
  8. {
  9. //老式
  10. Cat x = new Cat();
  11. x.name = "aa";
  12. x.age = 1;
  13.  
  14. //对象初始值设定项
  15. Cat x1 = new Cat
  16. {
  17. name = "aa",
  18. age = 1
  19. };
  20. Console.Write(x1.age);
  21. }

例2:嵌套应用

  1. class Rectangle
  2. {
  3. public Point P1 { set; get; }
  4. public Point P2 { set; get; }
  5.  
  6. public Rectangle()
  7. {
  8. P1 = new Point();
  9. P2 = new Point();
  10. }
  11. }

  1. void Main()
  2. {
  3. Rectangle myRec = new Rectangle
  4. {
  5. P1 = new Point() { X = 1, Y = 1 },
  6. P2 = new Point() { X = 200, Y = 200 }
  7. };
  8. Console.Write(myRec.P2.Y);
  9. }

2、集合初始值设定项

无需再代码中指定对该集合类的多个Add方法调用,编译器自动添加调用。

集合类必须实现IEumerable。

例1:

  1. List<int> list=new List<int> {0,1,2,3};

例2:

  1. List a = new List
  2. {
  3. new Rectangle {P1 = { X = 1, y = 1 },P2 = { X = 200, y = 200 },
  4. new Rectangle {P1 = { X = 1, y = 1 },P2 = { X = 200, y = 200 }
  5. } //如果Add方法允许,可以将null指定为其中的一个元素

例3、如果集合支持读取/写入索引,可以指定索引元素。

  1. var numbers = new Dictionary<int, string>
  2. {
  3. [7] = "seven",
  4. [9] = "nine",
  5. [13] = "thirteen"
  6. };

注意:前面的示例生成调用 Item[TKey] 以设置值的代码。 从 C# 6 开始,可以使用以下语法初始化字典和其他关联容器。  它使用具有多个值的对象,此初始值设定项示例调用 Add(TKey, TValue),将这三个项添加到字典中。

  1. var moreNumbers = new Dictionary<int, string>
  2. {
  3. {19, "nineteen" },
  4. {23, "twenty-three" },
  5. {42, "forty-two" }
  6. };

由于编译器生成的方法调用不同,这两种初始化关联集合的不同方法的行为略有不同。 这两种变量都适用于 Dictionary 类。 其他类型根据它们的公共 API 可能只支持两者中的一种。

五、匿名类型

匿名类型是编译器动态创建的一个类,用于存储一组值。

要创建匿名类型,请使用new关键字和对象初始化器,指定类型将包含的属性和值。

可以将一组只读属性封装到单个对象中,无需首先定义一个类型。匿名类型只能用于定义它的方法中。

匿名类型由一个或多个公共只读属性组成。成员不能用null赋初值。如果多个匿名类型有相同数量和种类的属性,编译器将视为相同的类型,生成多个实例。

  1. var noName = new { name = "a",
  1. age = 1 };
  2. Console.Write(noName.name);

1、匿名类型的属性名称可以从表达式中推断出来:

  1. int Age = 3;
  2. var person = new { Name = "Jack", Age, Age.ToString().Length };

相当于:

  1. var person = new { Name = "Jack", Age = Age, Length = Age.ToString().Length };

2、由匿名类型构成的数组

  1. var anonArray = new[] { new { name = "apple", diam = 4 },
  1. new { name = "grape", diam = 1 }};

生成匿名类型数组

  1. var result = new
  2. {
  3. pages = 10,
  4. Users = from mo in list
  5. select new
  6. {
  7. id = mo.UserId,
  8. name = mo.Nick
  9. }
  10. };

可以生成:

  1. var result = new
  2. {
  3. pages = 10,
  4. users = new[]{
  5. new{id=1,name="2"}
  6. new{id=2,name="3"}
  7. }
  8. }

3、由匿名类型构成的列表和字典

  1. var a1 = new List<dynamic>() {
  2. new { X = 100, Y = 200 },
  3. new { X = 300, Y = 400}
  4. };
  5.  
  6. Console.Write(a1[1].X);
  7.  
  8. var moreNumbers = new Dictionary<dynamic, dynamic>
  9. {
  10. {19, "nineteen" },
  11. {23, "twenty-three" },
  12. {42, "forty-two" }
  13. };
  14.  
  15. Console.Write(moreNumbers[19]);

4、在Linq 中使用

匿名类型通常用在查询表达式的 Select 子句中,以便返回原序列中每个对象的属性子集(Linq 中使用的比较多)。

  1. class MyClass
  2. {
  3. public string Name { set; get; }
  4. public int Number { set; get; }
  5. }
  6.  
  7. void Main()
  8. {
  9. MyClass[] list = new MyClass[12];
  10. var varbj = from obj in list
  11. select new { obj.Name,
  1. ID=obj.Number};
  2. foreach (var v in varbj)
  3. {
  4. Console.Writ(v.Name, v.ID);
  5. }
  6. }

5、应用

匿名类型对象的传递

  1. void Main()
  2. {
  3. //匿名类型
  4. var news = new { title = "冰红茶", day = "2019-4-10", author = "康师傅" };
  5. ShowInfo(news);
  6. }
  7.  
  8. static void ShowInfo<T>(T news)
  9. {
  10. dynamic d = news;
  11. Console.WriteLine(d.title);
  12. Console.WriteLine(d.day);
  13. Console.WriteLine(d.author);
  14. }

用匿名类型填充数组,并计算总年龄

  1. var family = new[] //使用隐式类型的数组初始化程序
  2. {
  3. new { Name = "Holly", Age = 37 }, //同一个匿名类型连用5次
  4. new { Name = "Jon", Age = 36 },
  5. new { Name = "Tom", Age = 9 },
  6. new { Name = "Robin", Age = 6 },
  7. new { Name = "William", Age = 6 }
  8. };
  9.  
  10. int totalAge = 0;
  11. foreach (var person in family) //totalAge累加 对每个人使用
  12. {
  13. totalAge += person.Age;
  14. }
  15. Console.WriteLine("Total age: {0}", totalAge);

六、Lambda表示式

(详细见https://www.cnblogs.com/springsnow/p/9441946.html

是一个匿名函数,它可以包含表达式和语句,可用于创建委托或表达式目录树类型。

从 C# 1.0 - 3.0委托示例

  1. ///
  2. /// C# 1.0 - 3.0 委托的发展过程
  3. ///
  4.  
  5. public class DelegateEvlove
  6. {
  7. //方法1 定义委托
  8. public delegate void TestDelegate(string s);
  9.  
  10. static void ConsoleStr(string s)
  11. {
  12. Console.WriteLine(s);
  13. }
  14.  
  15. public static void Main(string[] args)
  16. {
  17. //方法1 实例化委托
  18. TestDelegate iDelegate = new TestDelegate(ConsoleStr);
  19. //方法1 调用委托
  20. iDelegate("1 instance delgate");
  21.  
  22. //方法2 匿名委托
  23. TestDelegate aDelegate = delegate (string s) { Console.WriteLine(s); };
  24. aDelegate("2 anonymous delegate");
  25.  
  26. //方法3 lambda 表达式
  27. TestDelegate lDelegate = (s) => { Console.WriteLine(s); };
  28. lDelegate("3 lambda delegate");
  29.  
  30. }
  31. }

1、简单应用

将λ表达式分配给委托类型,同delegate(int x){retun x*x}(匿名函数)

  1. delegate int del(int i);
  2. void Main()
  3. {
  4. del myDel = x => x * x;//或 x=>{return x*x };
  5. int j = myDel(5);
  6. Console.Write(j);
  7. }

2、事件处理程序

当λ表达式有一个输入参数时,括号是可选的。使用空括号指定0个输入参数。也可以显示指定参数类型

  1. public static event EventHandler myEvent;
  2. void Main()
  3. {
  4. myEvent += (s, e) => { Console.Write(s); };
  5. //即myEvent += delegate(object s,EventArgs e) => { Console.Write(s); };
  6. myEvent(this, null);
  7. }

3、创建表达式树类型

  1. using System.Linq.Expressions;
  2. Expression = x=>x*x;

七、Linq表达式

1、简单应用:

检索所有Sex为false的人,查询结果放到results变量中,results变量与数组persons类型相同

  1. using System.Linq;
  2.  
  3. var persons = new[] { new { Name = "var", Sex = false },
  1. new { Name = "var2", Sex = false } };
  2. var results = from p in persons//
  1. where p.Sex == false
  2. select p;
  1. foreach (var person in results)
  2. {
  3. Console.Write(person.Name);
  4. }

2、嵌套成员:

检索所有城市为伦敦,且订单日期为2018年以后的所有记录,查询结果是一个匿名类型的数组。

  1. var customers = new[] { new { Name = "var",City="China" ,Orders = new []{new{OrderNO=0,OrderDate=new DateTime(2017,1,1)},
  2. new{OrderNO=1,OrderDate=new DateTime(2018,1,1)}, }},
  3. new { Name = "Vicky",City="London" ,Orders = new []{new{OrderNO=2,OrderDate=new DateTime(2019,9,1)},
  4. new{OrderNO=3,OrderDate=new DateTime(2018,1,1)}, } }
  5. };
  6.  
  7. var someCustomers = from c in customers
  8. where c.City == "London"
  9. from o in c.Orders
  10. where o.OrderDate.Year > 2018
  11. select new { c.Name, o.OrderNO };
  12.  
  13. foreach (var customer in someCustomers)
  14. {
  15. Console.Write(customer.Name + customer.OrderNO);
  16. }

八、表达式树

一种有效的数据表达方式,以树的形式显示λ表达式。这些所有数据表达方式可以同时进行编译。

1、如果操作符被声明为可以接受一个方法委托,则编译器将生成IL代码。

  1. public static IQueryable Where(this IEnumerable source,Func predicate);

2、如果操作符被声明为可以接受一个方法委托“表达式”,则编译器将生成一个表达式树。

  1. public static IQueryable Where(this IQueryable source,Expression > predicate);

C#3.0新特性:隐式类型、扩展方法、自动实现属性,对象/集合初始值设定、匿名类型、Lambda,Linq,表达式树、可选参数与命名参数的更多相关文章

  1. C#3.0新增功能06 对象和集合初始值设定项

    连载目录    [已更新最新开发文章,点击查看详细] 使用 C# 可以在单条语句中实例化对象或集合并执行成员分配. 对象初始值设定项 使用对象初始值设定项,你可以在创建对象时向对象的任何可访问字段或属 ...

  2. 从C# 2.0新特性到C# 3.5新特性

    一.C# 2.0 新特性: 1.泛型 List<MyObject> obj_list=new List(); obj_list.Add(new MyObject()); 2.部分类(par ...

  3. C# 9.0 新特性预览 - 类型推导的 new

    C# 9.0 新特性预览 - 类型推导的 new 前言 随着 .NET 5 发布日期的日益临近,其对应的 C# 新版本已确定为 C# 9.0,其中新增加的特性(或语法糖)也已基本锁定,本系列文章将向大 ...

  4. [翻译] C# 8.0 新特性 Redis基本使用及百亿数据量中的使用技巧分享(附视频地址及观看指南) 【由浅至深】redis 实现发布订阅的几种方式 .NET Core开发者的福音之玩转Redis的又一傻瓜式神器推荐

    [翻译] C# 8.0 新特性 2018-11-13 17:04 by Rwing, 1179 阅读, 24 评论, 收藏, 编辑 原文: Building C# 8.0[译注:原文主标题如此,但内容 ...

  5. C#6.0,C#7.0新特性

    C#6.0新特性 Auto-Property enhancements(自动属性增强) Read-only auto-properties (真正的只读属性) Auto-Property Initia ...

  6. C#7.0&6.0新特性 — 完整版

    C#2.0 泛型 部分类型 匿名方法 迭代器 可空类型 Getter / setter单独可访问性 方法组转换(代表) Co- and Contra-variance for delegates 静态 ...

  7. [转] Scala 2.10.0 新特性之字符串插值

    [From]  https://unmi.cc/scala-2-10-0-feature-string-interpolation/ Scala 2.10.0 新特性之字符串插值 2013-01-20 ...

  8. Android 7.0新特性

    还望支持个人博客站:http://www.enjoytoday.cn 由于google目前不是无法直接在国内访问,故此,对于android 开发平台的7.0新特性做个保存.也可供大家查阅.原文转自an ...

  9. C# 9.0 新特性预览 - 空参数校验

    C# 9.0 新特性预览 - 空参数校验 前言 随着 .NET 5 发布日期的日益临近,其对应的 C# 新版本已确定为 C# 9.0,其中新增加的特性(或语法糖)也已基本锁定,本系列文章将向大家展示它 ...

随机推荐

  1. [java] byte不能直接相加

    以下赋值语句将产生一个编译错误,原因是赋值运算符右侧的算术表达式在默认情况下的计算结果为 int 类型. // Error: conversion from int to byte:byte z =  ...

  2. js控制div样式显示与隐藏,JS通过点击超链接右边(指定位置)显示一个图标

    原文出自:https://blog.csdn.net/seesun2012 javascript基础篇,老土的方法解决js控制div样式,便于新手理解,粗暴的不能再粗暴,如果你是高手,请忽略! 思路: ...

  3. Redis 【string】 一句话说明

    APPEND----------------------------------------------在字符串后面追加 BITCOUNT------------------------------- ...

  4. C# 请求Https

    /// <summary> /// Get请求 /// </summary> /// <param name="Url"></param& ...

  5. ETL第二篇 调用webservice

    ETL第一篇(Kettle Spoon) 初遇 ETL第二篇 调用webservice 前言 这里使用ETL [Java代码] 实现 代码中使用axis调用webservice 在ETL提供了 Pro ...

  6. MySQL数据源驱动报错

    报错信息:MySQL数据源驱动报错: 1.mysql8.0以上版本需要连接数据库的JDBC驱动也是8.0版本以上 com.mysql.cj.jdbc.Driver 2.MySQL高版本需要指明是否需要 ...

  7. NIO与Socket

    一.Socket 的使用 1.单线程Socket的使用 /** * 单线程版本 * 问题描述:只能服务单个客户端 * 解决方案:多线程版本 */ public class Socket_V1 { pu ...

  8. K:hash的应用场景

    本博文主要用于讲解Hash的应用场景 Hash主要应用于数据结构中和密码学中. 用于数据结构时,主要是为了提高查询的效率,这就对速度比较重视,对抗碰撞不太看中,只要保证hash均匀分布就可以. 在密码 ...

  9. jquery each遍历判断返回false方法

    在jquery each中遍历返回false失效,解决办法,用变量解决: var num = 0; $(".box").find("input[type='text']& ...

  10. word-wrap,word-break,white-space

    这3个属性都与换行有关,看看有啥区别. 语法介绍 [word-wrap] 定义:属性允许长单词或 URL 地址换行到下一行: 语法: word-wrap: normal|break-word; bre ...