建议25:谨慎集合属性的可写操作

如果类型的属性中有集合属性,那么应该保证属性对象是由类型本身产生的。如果将属性设置为可写,则会增加抛出异常的几率。一般情况下,如果集合属性没有值,则它返回的Count等于0,而不是集合属性的值为null。下面的代码将产生一个NullReferenceException异常:

    class Program
{
static List<Student> listStudent = new List<Student>()
{
new Student(){ Name = "Mike", Age = },
new Student(){ Name = "Rose", Age = }
}; static void Main(string[] args)
{
StudentTeamA teamA = new StudentTeamA();
Thread t1 = new Thread(() =>
{
teamA.Students = listStudent;
Thread.Sleep();
Console.WriteLine(listStudent.Count); //模拟对
//集合属性进行一些运算
});
t1.Start();
Thread t2 = new Thread(() =>
{
listStudent = null; //模拟在别的地方对list1而
//不是属性本身赋值为null
});
t2.Start();
}
} class Student
{
public string Name { get; set; }
public int Age { get; set; }
} class StudentTeamA
{
public List<Student> Students { get; set; }
}

上面代码的问题是:线程t1模拟将对类型StudentTeamA的Students属性进行赋值,它是一个可读/可写的属性。由于集合属性是一个引用类型,而当前针对该属性对象的引用却又两个,即集合本身和调用者的类型变量listStudent,线程t2也许是另一个程序员写的,但他看到的只有listStudent,结果,针对listStudent的修改hi直接影响到另一个工作线程的对象。在例子中,我们将listStudent赋值为null,模拟在StudentTeamA(或者说工作线程t1)不知情的情况下使得集合属性变为null。接着,线程t1模拟针对Students属性进行若干操作,导致抛出异常。

下面的StudentTeamA版本是一个改进过的版本。首先,将类型的集合属性设置为只读;其次,集合对象由类型自身创建,这保证了集合属性永远只有一个引用:

    class Program
{
static List<Student> listStudent = new List<Student>()
{
new Student(){ Name = "Mike", Age = },
new Student(){ Name = "Rose", Age = }
}; static void Main(string[] args)
{
StudentTeamA teamA2 = new StudentTeamA();
teamA2.Students.Add(new Student() { Name = "Steve", Age = });
teamA2.Students.AddRange(listStudent);
Console.WriteLine(teamA2.Students.Count);
//也可以像下面这样实现
StudentTeamA teamA3 = new StudentTeamA(listStudent);
Console.WriteLine(teamA3.Students.Count);
} class Student
{
public string Name { get; set; }
public int Age { get; set; }
} class StudentTeamA
{
public List<Student> Students { get; private set; } public StudentTeamA()
{
Students = new List<Student>();
} public StudentTeamA(IEnumerable<Student> studentList)
: this()
{
Students.AddRange(studentList);
}
}

在改进版本的StudentTeamA中尝试对属性Students进行赋值:

 teamA.Students = listStudent;

将导致编译通不过。

转自:《编写高质量代码改善C#程序的157个建议》陆敏技

最新文章

  1. Bootstrap v4.0.0-alpha.5 发布,大量更新
  2. Senparc.Weixin.MP SDK 微信公众平台开发教程(四):Hello World
  3. Parencodings(imitate)
  4. mysql计划任务
  5. Different ways to invoke a shared object/share library(.so)
  6. 利用 Composer 一步一步构建自己的 PHP 框架(三)——设计 MVC
  7. POJ 3621Sightseeing Cows
  8. 3、使用Gradle创建Libgdx项目
  9. org.elasticsearch.client.transport.NoNodeAvailableException
  10. 3ds max学习笔记(二)--查看视点
  11. 厨娘ui设计文档
  12. Certificate Formats | Converting Certificates between different Formats
  13. css:自己实现一个带小图标的input输入框
  14. [转]Linux系统下如何查看及修改文件读写权限
  15. 论asp.net out、ref、return
  16. 有人在群里问关于SQL表组合数据问题
  17. 通过iscsi协议使用ceph rbd
  18. Effective JavaScript Item 33 让构造函数不再依赖newkeyword
  19. 激活pycharm
  20. Mockplus原型设计工具介绍

热门文章

  1. BZOJ2084:[POI2010]Antisymmetry
  2. 读写另一EXE的内存
  3. Qt开发环境下载和安装
  4. 浅谈FPGA有限状态机
  5. QQ市场总监分享:黏住90后的独门攻略
  6. [原创]Java项目统一UTC时间方案
  7. Mycat实战之离散分片
  8. 前端html数组去重的方法
  9. document.ready与window.load区别
  10. 刷题向》图论》BZOJ1001 平面图最大流、平面图最小割、单源最短路(easy+)