c#2.0新特性

范型

我们知道通用的数据结构可以采用object存储任何数据类型。使用object问题是:

  • 显示的强制转带来的代码复杂性
  • 换装箱拆箱的性能损失(为什么有性能损失?因为涉及动态内存分配和运行时类型检查)。还有一些运行时才会出现的类型转换异常也是我们难以在代码编写的时候能够检查到的,防不胜防。

范型应时而生,它的思路是什么呢?它接受带有类型参数并存储这个类型而不转换它,类型参数在类名字后的<T>中指定。T相当于一个占位符,直到使用的时候才指定一个实际的类型。确切的说当应用程序首次创建一个构造范型类型的实例时,.net公共语言运行时的实时编译器JIT将在进程中把范型IL和元数据转化为本地代码并把类型参数转化为实际的类型。对于这个泛型类型的后续引用将会使用相同的本机代码。这也就是传说中的范型类型实例化。

看一段代码:

范型的一个有趣话题:约束

问题溯源:由于T代表的可能是任何类型,所以我们使用T的方法仅限于Equals GetHasCode ToString,那么我们要使用某些特定数据类型的方法呢?比如实现了IComparable接口的数据类型的CompareTo方法?

一种方法是强制转换到IComparable接口。这种方法的缺点是:1.进行运行时动态类型检查增加了性能上的开销,2.自然地如果key没有实现IComparable接口的异常报告推迟到了运行时

另一种方法就是约束列表,关键词是where,后面跟的是类或者接口的列表,还有一个可选、特殊的new()约束;其实就是说这个类型必须要有一个公开无参构造函数,这就允许泛型类使用这种构造函数来创建实例。约束是一把双刃剑,一方面它提供了编译时类型检查,增强了性能,但是它也限制了范型类型的能力。

范型方法
范型方法在方法名字后面使用<>指定一个或者多个类型参数,类型参数可以出现在参数列表,返回类型和方法体内。编译器会使用一种类型推断的机制通过其他参数类推断正确的类型参数。

给出一些范型的例子:

Code
  1 public class Test<T>
  2    {
  3        public T item { get; set; }
  4
  5        public void Display()
  6        {
  7            Console.WriteLine(item.ToString());
  8        }
  9
 10    }
 11
 12    public class Map<K, V>
 13    {
 14        Dictionary<K, V> d = new Dictionary<K, V>();
 15        public void Add(K key, V value)
 16        {
 17
 18            d.Add(key, value);
 19        }
 20        public void Display()
 21        {
 22            foreach (var item in d.Keys)
 23            {
 24                Console.WriteLine("Key:" + item + " Value:" + d[item]);
 25            }
 26        }
 27    }
 28
 29    public class ComparableTest<T> where T : IComparable
 30    {
 31        public T item { get; set; }
 32
 33        public void Display()
 34        {
 35            if (item.CompareTo(10) > 0)
 36            {
 37                Console.WriteLine(item.ToString() + ">" + "10");
 38            }
 39            else
 40            {
 41                Console.WriteLine(item.ToString() + "<" + "10");
 42            }
 43        }
 44
 45    }
 46
 47    public class MapWithConstraint<K, V> where V : new()
 48    {
 49        Dictionary<K, V> d = new Dictionary<K, V>();
 50        public void Add(K key, V value)
 51        {
 52
 53            d.Add(key, value);
 54        }
 55        public void Display()
 56        {
 57            foreach (var item in d.Keys)
 58            {
 59                Console.WriteLine("Key:" + item + " Value:" + d[item]);
 60            }
 61        }
 62    }
 63
 64    public class GenericMethodTest
 65    {
 66        public T  Display<T, V, K>(T t, K k, V v)
 67        {
 68            Console.WriteLine(t.ToString() + "  " + k.ToString() + " " + v.ToString());
 69            return t ;
 70        }
 71    }
 72    public class Student
 73    {
 74        public int ID { get; set; }
 75        public string Name { get; set; }
 76    }
 77 class Program
 78    {
 79        static void Main(string[] args)
 80        {
 81            Test<int> t = new Test<int>();
 82            t.item = 10;
 83            t.Display();
 84
 85
 86            Map<string, int> map = new Map<string, int>();
 87            map.Add("King", 23);
 88            map.Add("XiaoQiang", 24);
 89            map.Display();
 90
 91            ComparableTest<int > test = new ComparableTest<int >();
 92            test.item = 123;
 93             test.Display();
 94            
 95
 96           // ComparableTest<Student > test2 = new ComparableTest<Student >();
 97
 98
 99            GenericMethodTest g = new GenericMethodTest();
100            Console.WriteLine(g.Display(23, 32, 52));
101
102
103
104            Console.ReadLine();
105            
106        }
107    }
108

匿名方法

匿名方法其实就是体现了这样一个原则:如无必要,勿增实体;我们在一个简单的WinForm环境中来说明这个问题:一个按钮单击事件我们可以这样来定义响应代码。

 1   this.button1.Click += delegate
 2            {
 3                this.label1.Text = "King2002";
 4            };
 5            
 6            this.button1.Click += delegate(object sender, System.EventArgs arg)
 7            {
 8                this.label1.Text = "Test";
 9            };
10            this.button1.Click += new System.EventHandler(this.button1_Click);
11 private void button1_Click(object sender, EventArgs e)
12        {
13            MessageBox.Show("Hello");
14        }
15
16
17

匿名方法使得代码对于委托的实现更加简单,匿名方法还有一个用途就是操作一些私有成员,因为它相当于共享了一部分代码。

这里会有一个疑问:匿名方法和委托类型的隐式转换有什么要求?答案:只要参数列表和委托类型的返回值是兼容的就可以完成转换。

  • 参数列表兼容:无参数或者参数的数量、类型、修饰符严格匹配
  • 无返回类型,所有return语句形管的表达式可以被隐式转换到委托的类型

后面我们会看到更简单使用delegate的例子。

迭代器

一个对象如果是可枚举的,那么我们可以使用foreach语句来遍历其中的元素。实际上是调用了这个对象的GetEnumberator方法,它返回一个enumberator(枚举器)。实现枚举器很难但是我们可以使用迭代器实现!

 1 public class DaysOfTheWeek : System.Collections.IEnumerable
 2    {
 3        string[] m_Days = { "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat" };
 4
 5        public System.Collections.IEnumerator GetEnumerator()
 6        {
 7            for (int i = 0; i < m_Days.Length; i++)
 8            {
 9                yield return m_Days[i];
10            }
11        }
12    }
13
14    class TestDaysOfTheWeek
15    {
16        static void Main()
17        {
18            // Create an instance of the collection class
19            DaysOfTheWeek week = new DaysOfTheWeek();
20
21            // Iterate with foreach
22            foreach (string day in week)
23            {
24                System.Console.Write(day + " ");
25            }
26        }
27    }
28

上面是MSDN上的一个简单的例子,有了直观的印象我们可以深究一点:

迭代器是产生值的有序序列的一个语句块,迭代器不是一种成员,它只是实现函数成员的方式。Yield return语句产生迭代的下一个值 yield break 语句指明迭代已经完成;GetEnumerator返回值只要是枚举器接口或者是可枚举接口(System.Collections.IEnumerable   System.Collections.IEnumerator System.Collections.Generic.IEnumerable<T> System.Collections.Generic.IEnumerator<T> ),迭代器就可以被用做函数体。

不完整类型
不完整类型完全是为了更好的进行代码管理。仔细观察我们现在添加一个页面时,它的后代代码就使用了不完整类型:

public partial class _Default : System.Web.UI.Page 

c#3.0新特性

自动实现属性
Auto-Implemented Properties

 1public class Card
 2
 3    {
 4
 5        //这样的属性是不是简单多了?
 6
 7        public int ID { get; set; }
 8
 9        public string Password { get; set; }
10
11    }
12
13    class Customer
14
15    {
16
17        public double TotalPurchases { get; set; }
18
19        public string Name { get; private set; } // read-only
20
21        public int CustomerID { get; private set; } // read-only
22
23    }
24

  • 自动属性必须包含get set,如果是只读的就添加private关键字
  • Attributes 不允许使用自动属性,这里还是推荐使用常规的属性书写方式

<ms-help://MS.MSDNQTR.v90.en/dv_csref/html/aa55fa97-ccec-431f-b5e9-5ac789fd32b7.htm>

检索表达式

Query Expressions

LINQ毫无疑问是c#3.0最抢眼的东西,关于LINQ的文章已经很多,这里不展开,详细资料请参考:

<ms-help://MS.MSDNQTR.v90.en/dv_csref/html/40638f19-fb46-4d26-a2d9-a383b48f5ed4.htm>

int[] items = new int[] { 1, 2, 3, 4, 5 };

            IEnumerable<int> ints = from item in items

                                    where item > 2.5

                                    select item;

            foreach (var p in ints)

            {

                Console.WriteLine(p);

            } 

隐式类型变量
Implicitly Typed Variables (var)

内部变量的类型可以使用var而不是确切的类型。var关键字可以指示编译器通过右侧的初始化部分来推断实际的数据类型。

  var num = 5;

            var a = new[] { 2, 5, 6, 7 };

            // anon 被编译成匿名类型 注意下面的Name Age都没有定义

            var anon = new { Name = "Terry", Age = 34 };

            var list = new List<int>();

            using (var file = new System.IO.StreamReader(@"D:\http.txt", Encoding.Default))

            {

                Console.WriteLine(file.ReadLine());

                Console.WriteLine(anon.Name );

                Console.WriteLine(anon.Age );

            }

var的使用会有一些约束:<ms-help://MS.MSDNQTR.v90.en/dv_csref/html/b9218fb2-ef5d-4814-8a8e-2bc29b0bbc9b.htm>

对象、集合初始化

Object and Collection Initializers

设计完成之后生成了一些类代码,但是这里有一个问题就是属性代码的填写,在FX3.0属性代码的已经简化,

类的初始化也提供了更简单的书写方式;可以看一下下面代码段中c2的初始化,列表对象的初始化按照同样的格式也会大大的简化。

 1public class Card
 2
 3    {
 4
 5        //这样的属性是不是简单多了?
 6
 7        public int ID { get; set; }
 8
 9        public string Password { get; set; }
10
11    }
12
13    class Program
14
15    {
16
17        static void Main(string[] args)
18
19        {
20
21            //通常我们初始化一个对象是这样做的
22
23            Card c = new Card();
24
25            c.ID = 2002;
26
27            c.Password = "henghenghaxi";
28
29
30
31            //现在我们可以这样做
32
33            Card c2 = new Card { ID = 23, Password = "testnum" };
34
35
36
37            Console.WriteLine(c.ID.ToString() + " - " + c.Password);
38
39            
40
41            //列表的初始化
42
43            List<Card> cards = new List<Card>
44
45            {
46
47                new Card{ID=12,Password="12sfdgr"},
48
49                new Card{ID=13,Password="12sdfwsd"},
50
51                new Card{ID=14,Password="12jkhjh"},
52
53                new Card{ID=15,Password="1dfsed2"},
54
55                new Card{ID=16,Password="1sdfsd2"},
56
57
58
59            };
60
61                         //看下面的例子
62
63            List<int> digits = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
64
65            List<int> digits2 = new List<int> { 0 + 1, 12 % 3, MakeInt() };
66
67
68
69            Console.WriteLine(cards.Count.ToString());
70
71            Console.ReadLine();
72
73        }
74
75               static int MakeInt()
76
77        {
78
79            return DateTime.Now.Second;
80
81        }
82
83
84
85    }
86
87

匿名类型

Anonymous Types

匿名类型把一系列的只读属性封装在一个对象里面,而并没有指定这个对象的类型编译器会给这个对象类型一个名字,但是这个名字在代码级别是不可用的。

看下面的代码:

// anon 被编译成匿名类型 注意下面的Name Age都没有定义

var anon = new { Name = "Terry", Age = 34 };

//anon.Age = 23;

最后一行如果执行编译器会给出一个错误:

Property or indexer 'AnonymousType#1.Age' cannot be assigned to -- it is read only

这个错误信息可以印证上面的说法。继续扩展上面的代码,一起看:

var card = from c3 in cards

                       where c3.ID > 13

                       //select c3;

                       select new {MyID= c3.ID,MyPassword= c3.Password };

            foreach (var item in card )

            {

              Console.WriteLine(item.MyID.ToString()+"---"+item.MyPassword );

                

            }

这里的代码是匿名类型的一个典型应用,详细请查阅:

<ms-help://MS.MSDNQTR.v90.en/dv_csref/html/59c9d7a4-3b0e-475e-b620-0ab86c088e9b.htm>

扩展方法

Extension Methods

扩展方法是一个静态方法,可以关联在一种类型上,所以这个方法可以在他处调用。这样仿佛给某一个类型添加了方法!而实际上我们并没有改变原有的代码。

详情参阅:ms-help://MS.MSDNQTR.v90.en/dv_csref/html/175ce3ff-9bbf-4e64-8421-faeb81a0bb51.htm

public static class Test

{

public static string RemoveWhiteSpace(this string s)

{

return s.Replace(" ", "");

}

}

定义了上面的方法之后,我们可以在string类型上使用这个方法下面是在开发环境中的截图:

匿名方法

Anonymous Functions

 1delegate void Testdelegate(string s);
 2
 3        static void Show(string s)
 4
 5        {
 6
 7            Console.WriteLine(s);
 8
 9        }
10
11 //1.1里面我们这样做
12
13            Testdelegate t = new Testdelegate(Show);
14
15
16
17            //2.0
18
19            Testdelegate t2 = delegate(string str) { Console.WriteLine(str); };
20
21
22
23            //3.0
24
25            Testdelegate t3 = (X) => { Console.WriteLine(X); };
26
27            t("Kingtest1");
28
29            t2("20022396");
30
31            t3("20022458"); 
32

在3.0里面我们的代码使用了Lambda表达式,详情参阅:

ms-help://MS.MSDNQTR.v90.en/dv_csref/html/57e3ba27-9a82-4067-aca7-5ca446b7bf93.htm

Lambada表达式在C#3.0中的典型应用:

ms-help://MS.MSDNQTR.v90.en/fxref_system.core/html/5a7a3466-7d99-dea6-a9fa-04043f951573.htm

// Split the string into individual words.

            string[] words = sentence.Split(' ');



            // Prepend each word to the beginning of the 

            // new sentence to reverse the word order.

            string reversed = words.Aggregate((workingSentence, next) =>

                                                  next + " " + workingSentence);

            bool b = words.All(w => w.Length > 5);

            bool b2 = words.Any(w => w.Length > 10);

一句话体会:

c#新特性的应用需要我们深入的学习以及在团队范围内的知识共享,这样才不致于让代码显得怪异

From:http://www.cnblogs.com/me-sa/archive/2008/04/23/1166688.html

转载于:https://www.cnblogs.com/xujiaci/archive/2008/04/23/1166985.html

【收藏】C# 2.03.0新特性总结相关推荐

  1. 【Servlet3.0新特性】第03节_文件上传

    这是一个Web Project 首先是web.xml <?xml version="1.0" encoding="UTF-8"?> <web- ...

  2. Redis 6.0 新特性:多线程连环 13 问!

    来源 | 码大叔 责编 | Carol 封图 | CSDN付费下载自视觉中国 支持多线程的Redis6.0版本于2020-05-02终于发布了,为什么Redis忽然要支持多线程?如何开启多线程?开启后 ...

  3. mysql sdi_MySQL 8.0新特性: 数据字典

    一.概述 数据字典(Data Dictionary)中存储了诸多数据库的元数据信息,包括基本Database, table, index, column, function, trigger, pro ...

  4. Redis 6.0 新特性-多线程连环13问!

    来自:码大叔 导读:支持多线程的Redis6.0版本于2020-05-02终于发布了,为什么Redis忽然要支持多线程?如何开启多线程?开启后性能提升效果如何?线程数量该如何设置?开启多线程后会不会有 ...

  5. 返璞归真 asp.net mvc (10) - asp.net mvc 4.0 新特性之 Web API

    返璞归真 asp.net mvc (10) - asp.net mvc 4.0 新特性之 Web API 原文:返璞归真 asp.net mvc (10) - asp.net mvc 4.0 新特性之 ...

  6. 精进不休 .NET 4.0 (4) - C# 4.0 新特性之命名参数和可选参数

    [索引页] [源码下载] 精进不休 .NET 4.0 (4) - C# 4.0 新特性之命名参数和可选参数, 动态绑定(dynamic), 泛型协变和逆变, CountdownEvent, Barri ...

  7. Redis 6.0 新特性,多线程连环 13 问!

    导读:支持多线程的Redis6.0版本于2020-05-02终于发布了,为什么Redis忽然要支持多线程?如何开启多线程?开启后性能提升效果如何?线程数量该如何设置?开启多线程后会不会有线程安全问题? ...

  8. mysql 直方图统计_MySQL 8.0 新特性之统计直方图

    原标题:MySQL 8.0 新特性之统计直方图 | 译者简介 译者 韩杰·沃趣科技MySQL数据库工程师 熟悉mysql体系架构.主从复制,熟悉问题定位与解决 出品 沃趣科技 原文链接: https: ...

  9. Android5.0,6.0,7.0,8.0新特性整理

    背景 Android5.0(Android Lollipop)是谷歌公司2014年10月发布的全新安卓系统,至今已经两年多.然而由于国产手机对安卓ROM的深度定制或修改,以及手机厂商.芯片制造商.运营 ...

最新文章

  1. The application does not contain a valid bundle identifier.解决方法
  2. Microsoft Artificial Intelligence Conference(2018.05.21)
  3. DEDE文章列表加上序号效果
  4. Win32ASM学习[20]:子程序
  5. 前端学习(1735):前端系列javascript之TypeScript介绍
  6. LDR 、ADR介绍
  7. C语言中.h文件和.c文件如何理解?看完详细解析,小白也能懂!
  8. 全球首款光线追踪GPU
  9. 互联网大厂春节礼盒鄙视链
  10. USB手机数据线充电线电源线出口办理CE认证的流程
  11. GeoServer中使用SLD样式
  12. 感受亮度与光强,及马赫带效应
  13. 使用XMind编写测试用例
  14. linux服务器集群管理面板,AppNode-Linux 服务器集群管理面板安装教程
  15. 操作系统【用户接口】命令解释程序的主要功能、系统调用与一般过程调用的不同之处、系统调用的参数传递方式、系统调用的处理步骤
  16. 我的同学是计算机作文,我的同桌作文
  17. 排队器拦截_网络拦截器-一个好用的网络拦截器
  18. 液晶屏 TTL屏、LVDS屏、TMDS屏区别
  19. 为什么要标准化用户故事格式?
  20. 计算机控制电缆 规范,控制电缆和计算机电缆安全CQC认证要求变更的通知

热门文章

  1. ****CI框架源码阅读笔记7 配置管理组件 Config.php
  2. pgsql中忘记密码通过如下方式解决
  3. php补充安装扩展支持
  4. delphi中设置系统时间方法
  5. 多线程编程之线程绑定处理器核
  6. 使用Linux建立拨号服务器
  7. MSSQL差异备份取系统权限
  8. 5000万用户数据泄露,大数据时代隐私保护困难重重
  9. WPF绘制自定义窗口
  10. 手把手教你如何进行FileZilla的安装