菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
200
0

C#开发157

原创
05/13 14:22
阅读数 25785

 

C#开发157条建议

 

 

 

摘要: 前言 从.NET3.0开始,C#开始一直支持一个新特性:匿名类型。匿名类型由var、赋值运算符和一个非空初始值(或以new开头的初始化项)组成。匿名类型有如下基本特性:1、既支持简单类型也支持复杂类型。简单类型必须是一个非空初始值,复杂类型则是一个以new开头的初始化项。2、匿名类型的属性是只读的...阅读全文
posted @ 2014-05-07 11:30 aehyok 阅读(1070) | 评论 (2) 编辑

 

 

 

摘要: 前言 本文已更新至http://www.cnblogs.com/aehyok/p/3624579.html。本文主要学习记录以下内容: 建议23、避免将List作为自定义集合类的基类 建议24、迭代器应该是只读的 建议25、谨慎集合属性的可写操作建议23、避免将List作为自定义集合类的基类...阅读全文
posted @ 2014-04-14 10:44 aehyok 阅读(1902) | 评论 (7) 编辑

 

 

 

摘要: 前言 软件开发过程中,不可避免会用到集合,C#中的集合表现为数组和若干集合类。不管是数组还是集合类,它们都有各自的优缺点。如何使用好集合是我们在开发过程中必须掌握的技巧。不要小看这些技巧,一旦在开发中使用了错误的集合或针对集合的方法,应用程序将会背离你的预想而运行。 本文已更新至http://www.cnblogs.com/aehyok/p/3624579.html。本文主要学习记录以下内容: 建议20、使用泛型集合来替代非泛型集合 建议21、选择正确的集合 建议22、确保集合的线性安全建议20、使用泛型集合来替代非泛型集合http://www.cnblogs.com/aehyok...阅读全文
posted @ 2014-04-11 10:04 aehyok 阅读(2442) | 评论 (19) 编辑

 

 

 

摘要: 前言 软件开发过程中,不可避免会用到集合,C#中的集合表现为数组和若干集合类。不管是数组还是集合类,它们都有各自的优缺点。如何使用好集合是我们在开发过程中必须掌握的技巧。不要小看这些技巧,一旦在开发中使用了错误的集合或针对集合的方法,应用程序将会背离你的预想而运行。 本文已更新至http://www.cnblogs.com/aehyok/p/3624579.html。本文主要学习记录以下内容: 建议16、元素数量可变的情况下不应使用数组 建议17、在多数情况下使用foreach进行循环遍历 建议18、foreach不能代替for 建议19、使用更有效的对象和集合初始化建议16、元...阅读全文
posted @ 2014-04-03 15:06 aehyok 阅读(3616) | 评论 (23) 编辑

 

 

 

摘要: 前言 本文已更新至http://www.cnblogs.com/aehyok/p/3624579.html。本文主要学习记录以下内容: 建议13、为类型输出格式化字符串 建议14、正确实现浅拷贝和深拷贝 建议15、使用dynamic来简化反射实现建议13、为类型输出格式化字符串 有两种方法可以为类型提供格式化的字符串输出。 一种是意识到类型会产生格式化字符串输出,于是让类型继承接口IFormattable。这对类型来说,是一种主动实现的方式,要求开发者可以预见类型在格式化方面的要求。 更多的时候,类型的使用者需为类型自定义格式化器,这就是第二种方法,也是最灵活多变的方法,可以根据...阅读全文
posted @ 2014-04-01 09:23 aehyok 阅读(1678) | 评论 (7) 编辑

 

 

 

摘要: 前言 本文已更新至http://www.cnblogs.com/aehyok/p/3624579.html。本文主要学习记录以下内容: 建议10、创建对象时需要考虑是否实现比较器 建议11、区别对待==和Equals 建议12、重写Equals时也要重写GetHashCode建议10、创建对象时需要考虑是否实现比较器 有对象的地方就会存在比较,就像小时候每次拿着考卷回家,妈妈都会问你隔壁的那谁谁谁考了多少分呀。下面我们也来举个简单的例子,就是有几个人的Salary列表。我们根据基本工资来进行罗列: class Program { static void Ma...阅读全文
posted @ 2014-03-31 09:26 aehyok 阅读(1648) | 评论 (6) 编辑

 

 

 

摘要: 前言 本文首先亦同步到http://www.cnblogs.com/aehyok/p/3624579.html。本文主要来学习记录一下内容: 建议4、TryParse比Parse好 建议5、使用int?来确保值类型也可以为null 建议6、区别readonly和const的使用方法 建议7、将0值设为枚举的默认值 建议8、避免给枚举类型的元素提供显式的值 建议9、习惯重载运算符建议4、TryParse比Parse好 如果注意观察,除string之外的所有的基元类型。会发现它们都有两个将字符串转换为自身类型的方法:Parse和TryParse。以类型double为例。两者最大的区...阅读全文
posted @ 2014-03-28 10:33 aehyok 阅读(2304) | 评论 (23) 编辑

 

 

 

摘要: 前言 本文主要来学习记录前三个建议。 建议1、正确操作字符串 建议2、使用默认转型方法 建议3、区别对待强制转换与as和is其中有很多需要理解的东西,有些地方可能理解的不太到位,还望指正。建议1、正确操作字符串 字符串应该是所有编程语言中使用最频繁的一种基础数据类型。如果使用不慎,我们就会为一次字符串的操作所带来的额外性能开销而付出代价。本条建议将从两个方面来探讨如何规避这类性能开销: 1、确保尽量少的装箱 2、避免分配额外的内存空间先来介绍第一个方面,请看下面的两行代码:String str1="str1"+9;String str2="str2"+9阅读全文
posted @ 2014-03-27 14:13 aehyok 阅读(2341) | 评论 (10) 编辑

 

 

 

摘要: 前言 由于最近工作重心的转移,原来和几个同事一起开发的项目也已经上线了,而新项目就是在现有的项目基础上进行优化延伸扩展。打个比方,现在已经上线的项目行政案件的Web管理网站(代码还没那么多相比较即将要做的刑事案件吧),而新项目是刑事案件的Web管理网站,之后行政和刑事这两个网站是要合并的。前段时间...阅读全文
posted @ 2014-03-26 10:17 aehyok 阅读(4396) | 评论 (30) 编辑

编写高质量代码改善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会合并两次查询并生成一个最终的查询。

 
 

前言

  从.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会合并两次查询并生成一个最终的查询。

发表评论

0/200
200 点赞
0 评论
收藏