Valid tive C # Item 23: avoid returning references to internal class objects

Source: Internet
Author: User

Valid tive C # Item 23: avoid returning references to internal class objects

We know that defining a read-only attribute makes it impossible for the caller to modify the value of this attribute. However, this approach is not always possible. If we create an attribute that returns the reference type, the caller can perform any operations on these object members, including those that we do not expect. Consider the following example:

Public class mybusinessobject
{
Private dataset _ DS;
Public dataset data
{
Get
{
Return _ DS;
}
}
}

Mybusinessobject bizobj = new mybusinessobject ();
Dataset DS = bizobj. Data;
DS. Tables. Clear (); // All Tables are deleted.

Any client program of mybusinessobject can modify its internal dataset. The purpose of creating a read-only attribute is to hide internal members, but the client can perform any operation on it. This read-only property opens a channel in our class to expose internal Member references to the outside. The read-only attribute we want is not a readable and writable attribute.

This is the magic of the reference type. The object reference address is returned for any reference type. After we return the object reference address to the caller, the caller can directly operate the reference type on the corresponding address regardless of the read-only attribute of the class.

Obviously, we should avoid such a situation. For example, if we create an interface for the class and want all users to follow it, we do not want the user to obtain or modify the internal members of the class. We have four policies to protect internal members of a class from this threat: using value types, using immutable types, using interfaces for function restrictions, and using wrapper ).

The value type is transmitted through the interface itself. Any modifications made to the copy in the client program do not reflect the internal members of the class. The client can process copies of the value type at will, which will not cause any problems.

Immutable types are also safe. A typical example is the system. string class. We can return a string or any other unchangeable types because they cannot be modified. Any operations on the client will not affect the security of the internal members of the class.

The third method is to define an interface, through which the client program can use some of the functions of internal members. When creating a class, you can define a group of interfaces that contain different functions of the class. By exposing these functional interfaces, internal Member exposure can be minimized. The client program can only obtain the functions that we allow through interfaces, rather than all the functions of internal members. In the above example, we can avoid modifying dataset by exposing only the dataset class's ilistsource interface.

The last method for dataset is to use the package. Through the dataviewmanager class, we can obtain data in dataset, but we can avoid unnecessary operations on it:

Public class mybusinessobject
{
Private dataset _ DS;
Public dataview this [String tablename]
{
Get
{
Return _ DS. defaultviewmanager. createdataview (_ DS. Tables [tablename]);
}
}
}

Dataviewmanager can create dataview for data tables in dataset. When we use dataviewmanager, there is no way to modify the content of the data table in dataset. We can perform some operations on dataview, but these operations are not reflected on the data source.

Before discussing how to create real read-only data, let's talk about how to respond to the client's modifications to public data. This is very important, because we often need to display some data on the user interface and accept user modifications. Through data binding, we can provide the data to users. The datatable class has a series of events that allow us to easily implement the observer mode: our class can respond to any modifications initiated by any user. The datatable in dataset can evoke events, regardless of the modification of rows or columns. The columnchanging and rowchanging events are aroused before the modifications are submitted. The columnchanged and rowchanged events are aroused after the modifications are submitted.

When we want the client to only view data, we can create an unchangeable dataview for datetable. The dataview class contains some attributes so that we can choose whether to add, delete, modify, or store the data. We can create an indexer to return the dataview of the specified index:

Public class mybusinessobject
{
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;
}
}
}

Finally, we need to return the view of a specific data table through the ilist interface. We can use the ilist interface on any set, not just dataset. We cannot simply return a dataview. You can easily change its functional attributes. We return a list of unmodifiable objects. Through the ilist interface, we can ensure that the dataview object is not modified by external operations.

It is wrong to expose internal Member references to users and accept user modifications. We should pay attention to the reference of the internal members returned in the interface. Users may perform arbitrary operations on these references, such as calling the public methods of these internal members. We should restrict this direct access to internal members through interfaces or packaging methods. When we want the client to modify internal data, we should use the observer pattern to verify and respond to user operations.

Translated from Objective C #: 50 specific ways to improve your C # by Bill Wagner

Back to directory

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.