C#1.0版本 :
- 接口的隐式实现和显式实现 : 一遍情况下我们在继承接口时针对的接口的方法进行实现
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
/// <summary> /// 接口 /// </summary> public interface IUserInfo { //定义方法 void show(); } /// <summary> /// 实现类 /// </summary> public class UserInfo : IUserInfo { /// <summary> /// 实现方法 /// </summary> public void show() { Console.WriteLine("UserInfo的Show方法"); } }
这样的方式使得我们在业务逻辑中使用时必须要这样做
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
UserInfo u = new UserInfo(); u.show();
带来的问题是:高耦合
我们可以这样解决这样子来显示实现接口的方法就是当前方法名为:接口+要实现的方法名 ,带调用的时候可以如下调用(注意这是两段不一样的代码,请不要直接复制运行)
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
/// <summary> /// 实现方法 /// </summary> void IUserInfo.show() { Console.WriteLine("UserInfo的Show方法"); } ///调用 IUserInfo id = new UserDataInfo(); id.show();
C#2.0版本 :
- 匿名方法
- 协变和逆变
- 泛型
- 迭代器
- 可空类型
- 局部类型
泛型: 一般的我们想要编写一个通用的集合迭代器,会使用Object,这个是所有类型的基类,
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
public class DataBag { List<object> list = new List<object>(); public void Add(object data) { list.Add(data); } }
然后在使用时会采用转型的方式,但是这无疑会发生性能方面的问题,涉及到了装箱和拆箱,
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
public class DataBag { List<object> list = new List<object>(); public void Add(object data) { list.Add(data); } public void show() { foreach (var item in list) { (item as UserInfo).MyProperty = "测试"; } } } public class UserInfo { public string MyProperty { get; set; } }
喜迎泛型: 泛型类型参数也可以被限制。泛型约束是强大的,允许有限范围的可用类型参数,因为它们必须遵守相应的约束。有几种方法可以编写泛型类型参数约束,请参考以下语法:语法类型/方法名<T> where T : class,new
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
public class DataBag<T> where T : struct { /* T 是值类型*/ } public class DataBag<T> where T : class { /* T 可以是类接口等引用类型*/ } public class DataBag<T> where T : new() { /* T 必须有无参构造函数 */ } public class DataBag<T> where T : IPerson { /* T 继承IPerson */ } public class DataBag<T> where T : BaseClass { /* T 来源于BaseClass */ } public class DataBag<T> where T : U { /* T继承U, U也是泛型类型参数。 */ }
多个约束是允许的,我们只要用逗号分隔即可。类型参数约束立即被强制执行,这使得如果编译错误可以立即提醒我们。让我们看看下面DataBag类的约束条件。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
public class DataBag<T> where T : class,UserInfo { List<T> list = new List<T>(); public void Add(T data) { list.Add(data); } public void show() { foreach (var item in list) { item.MyProperty = "测试"; } } }
C#3.0版本
- 匿名类型
- 自动实现属性
- 表达树
- 扩展方法
- Lambda表达
- 查询表达式
Lambda表达式: 在有些时候我们需要对数据进行筛选过滤,一般地我们会使用循环遍历来解决这样的问题 :
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
List<int> list = new List<int>(); for (int i = 0; i < 20; i++) { list.Add(i); } //找到数字为15的那条数据 for (int i = 0; i < list.Count; i++) { if (list[i]==15) { Console.WriteLine(list[i]); } } foreach (var item in list) { if (item==15) { Console.WriteLine(item); } }
这是一个很普通寻常的循环遍历相信大家都会,但是一般的我们的类型都会输一个类一个引用类型,再比如我们需要统计时怎么去做?
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
class Program { static void Main(string[] args) { List<UserInfo> list = new List<UserInfo>(); list.Add(new UserInfo() { Age = 18, Name = "李磊" }); list.Add(new UserInfo() { Age = 20, Name = "韩梅梅" }); list.Add(new UserInfo() { Age = 21, Name = "玛丽" }); list.Add(new UserInfo() { Age = 18, Name = "夏洛" }); int Sum = list.Sum(u => u.Age); double Avg = list.Average(u=>u.Age); Console.WriteLine("集合中的用户总年龄是"+Sum+"平均年龄是 "+Avg); UserInfo ui = list.First(u => u.Name == "李磊"); Console.WriteLine(string.Format("筛选单个用户信息 {0}: 年龄:{1}",ui.Name,ui.Age)); List<UserInfo> list_ui = list.Where(u => u.Age==18).ToList(); Console.WriteLine(string.Format("筛选年龄为18岁的记录 一共有 {0} 人",list_ui.Count)); foreach (var item in list_ui) { Console.WriteLine(string.Format("用户信息 {0}: 年龄:{1}", item.Name, item.Age)); } } } public class UserInfo { public string Name { get; set; } public int Age { get; set; } }
C#4.0版本
- 动态绑定
- 嵌入式互操作类型
- 泛型协变和逆变
- 实名/可选参数
C#5.0版本
像C#4.0版本一样,C#5.0版本中没有太多功能 - 但是其中一个功能非常庞大。
- 异步/等待
- CallerInfoAttributes
C#6.0版本
C#6.0的推出有很多很大的进步,很难选择我最喜欢的功能。
- 字典初始化
- 异常过滤器
- 在属性里使用Lambda表达式
- nameof表达式
- 空值运算符
- 自动属性初始化
- 静态导入
- 字符串嵌入值
C#7.0版本
从所有集成到 C# 7.0的特性中。
- 更多的函数成员的表达式体
- 局部函数
- Out变量
- 模式匹配
- 局部变量和引用返回
- 元组和解构