Effective C# Item23:避免返回内部类对象的引用
2010-01-17 00:28
369 查看
当我们将属性置为只读后,就可以认为调用者对该属性的值不可以进行更改了吗?答案是否定的。对于值类型来说,将其置为只读,确实可以让调用者不能够对其进行修改;但是对于引用类型来说,调用者还是可以调用引用对象的公有成员,包括那些可以修改属性状态的成员。
我们来看下面的代码。
代码
上述代码中,结合了第三种方式和第四种方式,首先属性的返回值由DateView变成了IList,这样调用方只能够调用IList类型中定义的成员;其次,我们在返回IList之前,将DataView的AllowNew、AllowDelete和AllowEdit属性都设置为false,这样也能够阻止调用方对其进行改动。
总结:将引用类型通过公共接口暴露给外界,将使得类型的用户不用通过我们定义的方法和属性,就能够更改对象的内部结构,这违反了我们通常的直觉,会导致常见的错误。如果我们到处的是引用而非值,那就需要改变类型的接口,如果只是简单的返回内部数据,那么我们实际上就给外界赋予了访问内部成员的权限。客户代码可以调用成员中任何可用的方法。通过使用接口或者包装器对象向外界提供内部的私有数据,我们可以限制外界对它们的访问能力。当希望客户代码更改内部数据元素时,我们应该实现Observer模式,以使对象可以对更改进行校验或响应。
我们来看下面的代码。
代码
public class MyBusinessObject { // Read Only property providing access to a // private data member: private DataSet _ds; public IList this[ string tableName ] { get { DataView view = _ds.DefaultViewManager.CreateDataView ( _ds.Tables[ tableName ] ); view.AllowNew = false; view.AllowDelete = false; view.AllowEdit = false; return view; } } } // Access the dataset: IList dv = bizOjb[ "customers" ]; foreach ( DataRowView r in dv ) Console.WriteLine( r[ "name" ] );
上述代码中,结合了第三种方式和第四种方式,首先属性的返回值由DateView变成了IList,这样调用方只能够调用IList类型中定义的成员;其次,我们在返回IList之前,将DataView的AllowNew、AllowDelete和AllowEdit属性都设置为false,这样也能够阻止调用方对其进行改动。
总结:将引用类型通过公共接口暴露给外界,将使得类型的用户不用通过我们定义的方法和属性,就能够更改对象的内部结构,这违反了我们通常的直觉,会导致常见的错误。如果我们到处的是引用而非值,那就需要改变类型的接口,如果只是简单的返回内部数据,那么我们实际上就给外界赋予了访问内部成员的权限。客户代码可以调用成员中任何可用的方法。通过使用接口或者包装器对象向外界提供内部的私有数据,我们可以限制外界对它们的访问能力。当希望客户代码更改内部数据元素时,我们应该实现Observer模式,以使对象可以对更改进行校验或响应。
相关文章推荐
- 《Effective C#》读书笔记——条目26:避免返回对内部类对象的引用<使用C#表达设计>
- Effective C# 原则23:避免返回内部类对象的引用(翻译)
- EffectiveC#01--避免返回内部类对象的引用
- Effective C# 原则23:避免返回内部类对象的引用
- Effective C# Item23:避免返回内部类对象的引用
- Effective C# 避免返回内部类对象的引用
- Effective C++ Item 28 避免返回对象内部数据的引用或指针
- Effective C++ Item 28 避免返回对象内部数据的引用或指针
- C++箴言:必须返回对象时别返回引用
- 使用 Entity Framework 返回 JsonResult 时循环引用的避免【EF 转 JSON】
- 条款28:避免返回handles指向对象内部成分
- 避免创建不需要的对象,消除过期对象的引用
- 赋值运算符重载函数 返回引用和返回对象的区别
- c++返回函数局部对象的引用
- 为什么在匿名内部类中引用外部对象要加final修饰符
- effective C++ 条款 28:避免返回handles指向对象内部成分
- buffer的slice()方法返回的新buffer和原buffer引用的是同一个对象!!!修改千万要注意!
- 内部类引用外部类对象
- 类成员函数返回对象和返回引用的区别
- 条款21:必须返回对象object时,不要返回其引用reference