CLR.via.Csharp.3rd Chapter 5: Primitive, Reference, and Value Types
2010-07-11 21:24
525 查看
Programming Language Primitive Types
Any data types the compiler directly supports are called primitive types .I prefer to use the FCL type names(System.Int64) and completely avoid the primitive type names(long) .A primitive type name could map to different FCL type in different programming languages.
Checked and Unchecked Primitive Type Operations
The CLR has an instruction performs no overflow checking and another performs overflow checking for add,sub,mul,conv.Overflow checking operations execute a little slower because the CLR is checking these operations to determine whether an overflow occurred .Use the /checked+ compiler switch ,checked operator,checked and unchecked statements to control overflows .
Reference Types and Value Types
Reference type:class;Value Type:structure or an enumeration .For reference types:
The memory must be allocated from the managed heap .
Each object allocated on the heap has some additional overhead members associated with it that must be initialized (the type object pointer and the sync block index).
The other bytes in the object (for the fields) are always set to zero.
Allocating an object from the managed heap could force a garbage collection to occur .
Value type instances are usually allocated on a thread’s stack (although they can also be embedded as a field in a reference type object) . the variable contains the fields of the instance itself .
All of the structures are immediately derived from the System.ValueType.All enumerations are derived from the System.Enum abstract type, which is itself derived from System.ValueType .
Declare a type as a value type when:
The type acts as a primitive type .
The type doesn’t need to inherit from any other type .
The type won’t have any other types derived from it .
Instances of the type are small (approximately 16 bytes or less) .
Instances of the type are large (greater than 16 bytes) and are not passed as method parameters or returned from methods .
When you assign a value type variable to another value type variable, a field-by-field copy is made . When you assign a reference type variable to another reference type variable, only the memory address is copied .
Boxing and unboxing Value Types
It’s possible to convert a value type to a reference type by using a mechanism called boxing .Memory is allocated from the managed heap .
The value type’s fields are copied to the newly allocated heap memory .
The address of the object is returned .
When convert a reference type to a value type:
The address of the fields in the boxed object is obtained . This process is called unboxing .
The values of these fields are copied from the heap to the stack-based value type instance .
Boxing and unboxing/copy operations hurt application’s performance.
The value type instance being used to invoke the virtual method(such as Equals, GetHashCode, or ToString) is not boxed . However, if your override of the virtual method calls into the base type's implementation of the method, then the value type instance does get boxed.
Calling a nonvirtual inherited method (such as GetType or MemberwiseClone) always requires the value type to be boxed .
Casting an unboxed instance of a value type to one of the type’s interfaces requires the instance to be boxed.
Changing Fields in a Boxed Value Type by Using Interfaces (and Why You Shouldn’t Do This)
Some languages, such as C++/CLI, let you change the fields in a boxed value type, but C# does not . However, you can fool C# into allowing this by using an interface . An interface method is able to modify the fields of a boxed(pre-boxed) value type .Value types should be immutable so shouldn’t do this.
Object Equality and Identity
You should always call ReferenceEquals if you want to check for identity (if two references point to the same object) .Microsoft(and we) should have implemented Object’s Equals like this:
public class Object { public virtual Boolean Equals(Object obj) { // The given object to compare to can't be null if (obj == null) return false; // If objects are different types, they can't be equal. if (this.GetType() != obj.GetType()) return false; // If objects are same type, return true if all of their fields match // Since System.Object defines no fields, the fields match return true; } }
But, since Microsoft didn’t implement Equals this way, when a type overrides Equals, the override should call its base class’s implementation of Equals unless it would be calling Object’s implementation .
System.ValueType does override Object’s Equals method and is correctly implemented to perform a value equality check (not an identity check) . Internally, ValueType’s Equals method uses reflection .
When defining your own type, if you decide to override Equals, you must ensure that:
Equals must be reflexive; that is, x.Equals(x) must return true .
Equals must be symmetric; that is, x.Equals(y) must return the same value as y.Equals(x) .
Equals must be transitive; that is, if x.Equals(y) returns true and y.Equals(z) returns true, then x.Equals(z) must also return true .
Equals must be consistent . Provided that there are no changes in the two values being compared, Equals should consistently return true or false .
Object Hash Codes
If you define a type and override the Equals method, you should also override the GetHashCode method . The reason is that the implementation of the Hashtable type, the Dictionary type, and some other collections require that any two objects that are equal must have the same hash code value .Guidelines for selecting an algorithm for calculating hash codes :
Use an algorithm that gives a good random distribution for the best performance of the hash table .
Your algorithm can also call the base type’s GetHashCode method, including its return value . However Object’s or ValueType’s method doesn’t lend itself to highperformance hashing algorithms .
Your algorithm should use at least one instance field .
Ideally, the fields you use in your algorithm should be immutable.
Your algorithm should execute as quickly as possible .
Objects with the same value should return the same code .
You should never, ever persist hash code values . The reason is that hash code values are subject to change .
The dynamic Primitive Type
A dynamic expression is really the same type as System.Object . The compiler assumes that whatever operation you attempt on the expression is legal, so the compiler will not generate any warnings or errors . However, exceptions will be thrown at runtime if you attempt to execute an invalid operation .相关文章推荐
- CLR Via C# 3rd 阅读摘要 -- Chapter 5 - Primitive, Reference, and Value Types
- Primitive, Reference, and Value Types(Chapter 5 of CLR via C#)
- Type Fundamentals (.NET: Primitive types, reference types and value types )
- CLR via C# 总结之Chap5 Primitive, Reference, and Value Types
- Effective C# Item 6: Distinguish Between Value Types and Reference Types
- Item 18: Distinguish Between Value Types and Reference Types(Effective C#)
- Item 6: Distinguish Between Value Types and Reference Types
- Chapter1 Lua 中的转义字符 and get start with Lua ,Types and Value
- C# 2012 step by step 学习笔记8 CHAPTER 9 Creating Value types with enumerations and Structures
- Primitive Types and Reference Types in Javascript
- Distinguish Between Value Types and Reference Types - Effective C#学习笔记(6)
- C# Concepts: Value vs Reference Types
- parameters vs. arguments and call by value vs. call by reference
- !!!Chapter 2 Variable and Basic Types (2.1 ~ 2.3)
- MySQL 5.7 Reference Manual Chapter 13 Functions and Operators 参考手册第十三章函数与操作符内容总结
- Call-by-reference and Call-by-value
- Building, Packaging, Deploying, and Administering Applications and Types(Chapter 2 of CLR via C#)
- C++ Primer notes: Chapter 2. Variables and Basic Types
- Lengths of Primitive Java and C++ Data Types on Linux and Windows 32-bit/64-bit (Linux和Windows上Java和C++基本数据类型的长度对比32位/64位)
- C#值类型与引用类型(Value Type and Reference Type)