Objective tivec # _ 11

Source: Internet
Author: User

Item 18: distinguish between value types and reference types

 

● This is not c ++. You can define all types as value types and make a reference for them. This is not Java, and all types are value types. When creating each type of instances, you must determine the form in which they exist. This is an important decision that must be taken at the beginning to get the correct results. Value types or reference types? Structs or classes? When should you use each? This isn't c ++, in which you define all types as value types and can create references to them. this isn' t Java, in which everything is a reference type (unless you are one of the Language designers ). you must decide how all instances of your type will behave when you create it.

 

● In C #, you can declare a value type data with struct, or declare a reference type data with class. The value type data should be small and lightweight. The reference type is inherited from your class. This section describes how to use a data type in different ways, so that you can understand the differences between value-type data and reference-type data. Value types shocould be small, lightweight types. reference types form your class hierarchy. This section examines different uses for a type so that you understand all the distinctions between value types and reference types.

First, let's look at an example.

 
  PrivateMydata;
PublicMydata Foo ()
{
ReturnMydata;
}
//Call it:
Mydata v=Foo ();
Totalsum+ =V. value;

If mydata is of the value type, the return value is assigned and stored in the V variable. However, if mydata is a reference type, you will import a reference to an internal variable.

Or consider the following variables

  PublicMydata foo2 ()
{
ReturnMydata. createcopy ();
}
//Call it:
Mydata v=Foo ();
Totalsum+ =V. value;

 

Now, V is a value for the original mydata. As a reference type, two objects are created on the stack. You will not be troubled by exposing internal data. Instead, you create an additional object on the stack. If V is a local variable, it will soon be regarded as spam, and Clone requires you to perform type detection at runtime. All in all, this is inefficient. Now, V is a copy of the original mydata. as a reference type, two objects are created on the heap. you don't have the problem of exposing internal data. instead, you 've created an extra object on the heap. if V is a local variable, it quickly becomes garbage and clone forces you to use runtime type checking. all in all, it's inefficient.

Data exposed by public methods or attributes should be of the value type. However, this does not mean that all types returned from public members must be value types. ForCodeWhen mydata has data, its responsibility is to save the data. Types that are used to export data through public methods and properties shocould be value types. but that's not to say that every type returned from a public member shocould be a value type. there was an assumption in the earlier code snippet that mydata stores values. its responsibility is to store those values.

The following code snippet is taken into account:

  PrivateMytype;
PublicImyinterface foo3 ()
{
ReturnMytypeAsImyinterface;
}
//Call it:
Imyinterface ime=Foo3 ();
IME. dowork ();

 

The mytype variable is still returned from foo3. But this time, instead, access the internal data of the returned value, and access the object by calling a method on the defined interface. You are accessing a mytype object, not its specific data, but its behavior. This behavior is presented to us by the imyinterface. At the same time, this interface can be implemented by many other types. In this example, mytype is a reference type instead of a value type. The responsibility of mytype is to consider its behavior, not its data members.

 

● This simple code tells you the difference: the value type stores data and the reference type represents behavior. Now let's take a deeper look at how these types are stored in the memory and the performance of the storage model. That simple code snippet starts to show you the distinction: value types store values, and reference types define behavior. now look a little deeper at how those types are stored in memory and the performance considerations related to the storage models. consider this class:
Consider the following class:

  Public     Class C
{
Private Mytype = New Mytype ();
Private Mytype B = New Mytype ();
// Remaining implementation removed.
}
C cthing = New C ();

How many objects have been created? How much memory does it occupy? This is hard to say. If mytype is a value type, you only make one heap memory allocation. The size is exactly twice the size of mytype. However, if mytype is a reference type, you have made three heap memory allocations: one is a C object, which occupies 8 bytes, the other two times are allocated heap memory for the mytype object contained in the C object. The reason for this difference is that the value type exists in an object in an inline way. On the contrary, the reference type is not. Each reference type only retains one reference pointer, and data storage requires additional space.
To understand this, consider the following memory allocation:

 
  Mytype [] VaR= NewMytype [100];

 

If mytype is a value type data, 100 mytype space will be allocated at a time. However, if mytype is a reference type, only one memory allocation is required. Every data element is null. When you initialize each element in the array, You need to perform 101 allocation tasks-and the memory ratio of the 101 allocation takes more time. Allocating a large amount of reference data can cause fragmentation of the heap memory, thus reducingProgramPerformance. If the type you created is intended to store the value of the data, you need to select the value type.

● Using value type or reference type is a very important decision. Transforming a value type data into a class is a profound change. Consider the following situation:

  Public     Struct  Employee
{
// Properties elided
Public String Position
{
Get ;
Set ;
}
Public Decimal Currentpayamount
{
Get ;
Set ;
}
Public Void Pay (bankaccount B)
{
B. Balance + = Currentpayamount;
}
}

 

This is a clear example. This type contains a method that you can use to pay salaries for your employees. As time passes, your system is running normally. Next, you decided to grade different employees: the sales staff received the bonus and the manager got the bonus. You decided to change the employee type to a class:

  Public     Class  Employee
{
// Properties elided
Public String Position
{
Get ;
Set ;
}
Public Decimal Currentpayamount
{
Get ;
Set ;
}
Public Void Pay (bankaccount B)
{
B. Balance + = Currentpayamount;
}
}

 

This disrupts a lot of code that already exists and uses the structure you designed. The Return Value Type changes to the return reference type. The parameter is also transferred from the original value to the current reference. The behavior of the following code segment will be severely affected:

  
Employee E1 = Employees. Find (E => E. Position = " CEO " );
Bankaccount ceobankaccount = New Bankaccount ();
Decimal Bonus = 10000 ;
E1.currentpayamount + = Bonus; // Add one time bonus.
E1.pay (ceobankaccount );

 

This one-time bonus addition operation has become a continuous improvement. Once a copy of the value type, it is now a reference of the reference type. The compiler is happy to make this change for you, and your CEO is happy to make it. On the other hand, your CFO will report bugs to you. You still failed to change your opinion on the Value Type and reference type, so that you do not know that the mistake has changed your behavior!

This problem occurs because the employee no longer complies with the value-type data principle. In addition, it is defined as an element for saving data for empolyee. In this example, you must add a role for it: pay wages for employees. The responsibility is within the scope of the class. Classes can be defined with polymorphism, so it is easy to implement some common responsibilities; while the structure is not sufficient, it should be limited to saving data.

● When selecting between the value type and the reference type, we recommend that you consider the type size as a deciding factor in the. NET instruction document. In fact, more factors are the type of use. A simple structure or simple data carrier is an excellent candidate for value-type data. It turns out that value-type data has good performance in memory management: they have very few heap memory fragments, few are generated by garbage, and few are accessed indirectly. More importantly, when a method or attribute is returned, the value type is copy data. This is not a risk of exposing the internal structure. But you pay in terms of features. value types have limited support in object-oriented technology. You should regard all value types as closed. You can create a value type that implements the interface, but this requires packing. Principle 17 will explain to you that this will cause performance loss. Consider the value type as a data container. It is no longer an object in OO.

● You may create more reference types than each other. If you answer yes to all of the following questions, you should create value-type data. Compare the following problem with the previous example of employee:

1. Is data storage the most basic responsibility of data type? Is this type's principal responsibility data storage?
2. Does its attribute have a complete public interface to access or modify data members? Is its public interface defined entirely by properties that access its data members?
3. Are you sure this type will never have child classes? Am I confident that this type will never have subclasses?
4. Are you sure this type will never change? Am I confident that this type will never be treated polymorphically?

The value type is treated as a low-level data storage type, and the behavior of the application is represented by the reference type. You will obtain the copy of the security data from the method exposed by the class. You will get the advantage of high memory usage from the value type that uses inline. In addition, you can use standard object-oriented technology to create application logic. When you are not sure about the expected use, use the reference type.

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.