编写高质量代码改善C#程序的157个建议[匿名类型、Lambda、延迟求值和主动求值]

简介: 原文:编写高质量代码改善C#程序的157个建议[匿名类型、Lambda、延迟求值和主动求值]前言   从.NET3.0开始,C#开始一直支持一个新特性:匿名类型。匿名类型由var、赋值运算符和一个非空初始值(或以new开头的初始化项)组成。
原文: 编写高质量代码改善C#程序的157个建议[匿名类型、Lambda、延迟求值和主动求值]

前言

  从.NET3.0开始,C#开始一直支持一个新特性:匿名类型。匿名类型由var、赋值运算符和一个非空初始值(或以new开头的初始化项)组成。匿名类型有如下基本特性:

1、既支持简单类型也支持复杂类型。简单类型必须是一个非空初始值,复杂类型则是一个以new开头的初始化项。

2、匿名类型的属性是只读的,没有属性设置器,它一旦倍初始化就不可更改。

3、如果两个匿名类型的属性值相同,那么就任务这两个匿名类型相等。

4、匿名类型可以在循环中用作初始化器。

5、匿名类型支持智能感知。

6、匿名类型也可以拥有方法。  

本文已更新至http://www.cnblogs.com/aehyok/p/3624579.html 。本文主要学习记录以下内容:

  建议26、使用匿名类型储存LINQ查询结果

  建议27、在查询中使用Lambda表达式

  建议28、理解延迟求值和主动求值之间的区别

建议26、使用匿名类型储存LINQ查询结果

  我们直接来看一个简单的实例吧,假如现在有一个公司Company的实体类,然后又有一个人员的Person类,现在需要将Person类中的Name和Company类中的Name进行关联,而形成一个新的类型。

Compay类

    public class Company
    {
        public int ComparyId { get; set; }

        public string Name { get; set; }
    }

Person类

    public class Person
    {
        public int PersonId { get; set; }

        public string Name { get; set; }

        public int CompanyId { get; set; }
    }

简单初始化数据

            List<Company> companyList = new List<Company>() { 
                new Company(){ComparyId=1, Name="MicroSoft"},
                new Company(){ComparyId=2, Name="SamSung"}
            };
            List<Person> personList = new List<Person>() {
                new Person(){ PersonId=1,Name="aehyok",CompanyId=1},
                new Person(){ PersonId=2,Name="aehyok",CompanyId=2},
                new Person(){ PersonId=3,Name="aehyok",CompanyId=1},
                new Person(){ PersonId=4,Name="aehyok",CompanyId=2},
            };

下面来看最重要的部分

            var personWithCompany = from person in personList
                                    join company in companyList 
                                    on person.CompanyId equals company.ComparyId
                                    select new { PersonName = person.Name, CompanyName = company.Name };

其中new之前的代码是Linq关键字,new之后的代码就是匿名类型的初始化项。该匿名类型包含两个属性:PersonName和CompanyName。

            foreach(var item in personWithCompany)
            {
                Console.WriteLine(string.Format("{0}\t:{1}", item.PersonName, item.CompanyName));
            }
            Console.ReadLine();

调用结果如下所示

建议27、在查询中使用Lambda表达式

 Linq实际上是基于扩展方法和lambda表达式的,理解了这一点就不难理解Linq。任何Linq查询都能通过调用扩展方法的方式来替代。下面我们将建议26中的查询语句进行修改

修改之前

            var personWithCompany = from person in personList
                                    join company in companyList 
                                    on person.CompanyId equals company.ComparyId
                                    select new { PersonName = person.Name, CompanyName = company.Name };

修改之后

            var personWithCompany = from person in personList
                                    select new { PersonName = person.Name, CompanyName = person.CompanyId == 1 ? "MicroSoft" : "SamSung" };

当然还有另外一种方式

var personWithCompany = personList.Select(person => new { PersonName = person.Name, CompanyName = person.CompanyId == 1 ? "MicorSoft" : "SamSung" });

针对LINQ设计的扩展方法大多应用了泛型委托。System命名空间定义了泛型委托Action、Func、Predicate。可以这样理解这三个委托:Action用于执行一个操作,所以它没有返回值,Func用于执行一个操作并返回一个值,Predicate用于定义一组条件并判断参数是否符合条件。Select扩展方法接受的就是一个Func委托,而Lambda表达式其实就是一个简介的委托,运算符“=>”左边代表的是方法的参数,右边的是方法体。

下面我们再来举个简单的小例子,调用Where扩展方法,查找出“SamSung”公司的员工

            var personWithCompany = personList.Select(person => new { PersonName = person.Name, CompanyName = person.CompanyId == 1 ? "MicorSoft" : "SamSung" });
            foreach (var item in personWithCompany.Where(pItem => pItem.CompanyName == "SamSung"))
            {
                Console.WriteLine(item.PersonName);
            }

建议28、理解延迟求值和主动求值之间的区别

 我们先继续看一个简单的小例子:

        static void Main(string[] args)
        {
            List<int> list = new List<int>() { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            var temp1 = from c in list where c > 5 select c;
            var temp2 = (from c in list where c > 5 select c).ToList<int>();
            list[0] = 11;
            Console.Write("temp1:");
            foreach (var item in temp1)
            {
                Console.Write(item.ToString());
            }
            Console.Write("\ntemp2:");
            foreach (var item in temp2)
            {
                Console.Write(item.ToString());
            }
            Console.ReadLine();
        }

这代码很简单,看执行结果

在延迟求值的情况下,只是定义了一个查询,而且不是立刻执行。对查询结果的访问每次都会遍历原集合。如上文中对于temp1的迭代,在迭代之前,我们修改了list[0]的值,可以看到,修改直接影响了迭代的输出。对查询调用ToList、ToArray等方法,将会使其立即执行,由于对list[0]的修改是在temp2查询之后进行的,所以针对list[0]的修改不会影响到temp2的结果。

在使用Linq to SQL时,延迟求值能够带来显著的性能提升。举个例子:如果定义了两个查询:而且采用延迟求值,CLR会合并两次查询并生成一个最终的查询。

目录
相关文章
|
1月前
|
C# Windows
C#通过代码实现快捷键编辑
C#通过代码实现快捷键编辑
|
3月前
|
开发框架 .NET 编译器
C# 10.0中Lambda表达式的改进:更简洁、更灵活的代码编写体验
【1月更文挑战第21天】随着C#语言的不断发展,Lambda表达式作为一种简洁、高效的函数式编程工具,在C# 10.0中迎来了重要的改进。本文将详细探讨C# 10.0中Lambda表达式的新特性,包括参数类型的推断增强、自然类型的Lambda参数以及Lambda表达式的属性改进等。这些改进不仅简化了Lambda表达式的编写过程,还提升了代码的可读性和灵活性,为开发者带来了更优质的编程体验。
|
3月前
|
C# 开发者
C# 10.0中的文件范围命名空间:简化代码组织的新方式
【1月更文挑战第18天】C# 10.0引入了文件范围的命名空间,这是一种新的语法糖,用于更简洁地组织和管理代码。文件范围命名空间允许开发者在每个文件的基础上定义命名空间,而无需显式使用花括号包裹整个文件内容。本文将深入探讨文件范围命名空间的工作原理、使用场景以及它们为C#开发者带来的便利。
|
3月前
|
C# 开发者
C# 9.0中的模块初始化器:程序启动的新控制点
【1月更文挑战第14天】本文介绍了C# 9.0中引入的新特性——模块初始化器(Module initializers)。模块初始化器允许开发者在程序集加载时执行特定代码,为类型初始化提供了更细粒度的控制。文章详细阐述了模块初始化器的语法、用途以及与传统类型初始化器的区别,并通过示例代码展示了如何在实际项目中应用这一新特性。
|
3月前
|
编译器 C# 开发者
C# 9.0中的顶级语句:简化程序入口的新特性
【1月更文挑战第13天】本文介绍了C# 9.0中引入的顶级语句(Top-level statements)特性,该特性允许开发者在不使用传统的类和方法结构的情况下编写简洁的程序入口代码。文章详细阐述了顶级语句的语法、使用场景以及与传统程序结构的区别,并通过示例代码展示了其在实际应用中的便捷性。
|
4月前
|
存储 人工智能 C#
【Unity 3D】C#中数组、集合、栈、队列、哈希表、字典的讲解(附测试代码)
【Unity 3D】C#中数组、集合、栈、队列、哈希表、字典的讲解(附测试代码)
36 0
|
1月前
|
Java C# 开发工具
第一个C#程序
第一个C#程序
12 0
|
1月前
|
数据采集 存储 C#
抓取Instagram数据:Fizzler库带您进入C#程序的世界
在当今数字化的世界中,数据是无价之宝。社交媒体平台如Instagram成为了用户分享照片、视频和故事的热门场所。作为开发人员,我们可以利用爬虫技术来抓取这些平台上的数据,进行分析、挖掘和应用。本文将介绍如何使用C#编写一个简单的Instagram爬虫程序,使用Fizzler库来解析HTML页面,同时利用代理IP技术提高采集效率。
抓取Instagram数据:Fizzler库带您进入C#程序的世界
|
2月前
|
数据采集 JSON 前端开发
从代码到内容:使用C#和Fizzler探索Instagram的深处
Instagram是一个流行的社交媒体平台,拥有数亿的用户和海量的图片和视频内容。如果您想要从Instagram上获取一些有用的信息或数据,您可能需要使用爬虫技术来自动化地抓取和分析网页内容。本文将介绍如何使用C#和Fizzler这两个强大的工具,来实现一个简单而高效的Instagram爬虫,从代码到内容,探索Instagram的深处。
|
3月前
|
存储 传感器 监控
工业相机如何实现实时和本地Raw格式图像和Bitmap格式图像的保存和相互转换(C#代码,UI界面版)
工业相机如何实现实时和本地Raw格式图像和Bitmap格式图像的保存和相互转换(C#代码,UI界面版)
31 0