Explore the immutable data types of c,

Source: Internet
Author: User

Explore the immutable data types of c,

Reading directory:

Immutable object

Immutable: once an object is created and initialized, its values cannot be changed, and a new object will be generated for each subsequent change.

var str="mushroomsir";str.Substring(0, 6)

The string in c # is immutable. Substring (0, 6) returns a new string value, while the original string remains unchanged in the shared domain. Another StringBuilder is variable, which is also the reason why StringBuilder is recommended.

var age=18; 

When the memory with the storage value 18 is allocated to the age variable, its memory value cannot be modified.

age=2;

At this time, a new value 2 will be opened in the stack and assigned to the age variable, instead of changing the value in the memory of 18. int Is also immutable in c.

Class Contact {public string Name {get; set;} public string Address {get; set;} public Contact (string contactName, string contactAddress) {Name = contactName; address = contactAddress ;}}var mutable = new Contact ("ermao", "Tsinghua"); mutable. name = "Mao"; mutable. address = "Peking University ";

We instantiate MutableContact and assign it to mutable. Then we can modify the internal field value of the MutableContact object. It is not an initial value and can be called a mutable object.

Variable objects are shared in multi-thread concurrency, which causes some problems. Under multithreading, thread A assigns A value to Name = "Da Mao". Other threads may read the following data:

Mutable. Name = "Mao"; mutable. Address = "Tsinghua ";

Obviously, data integrity cannot be guaranteed, and data is also called a tear. We change a mutable object to an immutable object as follows:

public class Contact2{    public string Name { get; private set; }    public string Address { get; private set; }    private Contact2(string contactName, string contactAddress)    {        Name = contactName;        Address = contactAddress;                   }    public static Contact2 CreateContact(string name, string address)    {        return new Contact2(name, address);    }}

The Name and Address fields can only be initialized through the constructor of Contact2. Contact2 is an immutable object because the object itself is an immutable whole. By using immutable objects, you do not need to worry about data integrity, but also ensure data security and will not be modified by other threads.

Custom immutable set

When we enumerate a mutable set, we often need to lock the set out of thread security considerations to prevent it from being modified in other threads. Using an immutable set can avoid this problem. The data structure we usually use is implemented in a variable mode. How can we implement an immutable data structure! The stack is used as an example. The Code is as follows:

Public interface IStack <T>: IEnumerable <T> {IStack <T> Push (T value); IStack <T> Pop (); T Peek (); bool IsEmpty {get ;}} public sealed class Stack <T>: IStack <T> {private sealed class EmptyStack: IStack <T> {public bool IsEmpty {get {return true;} public T Peek () {throw new Exception ("Empty stack ");} public IStack <T> Push (T value) {return new Stack <T> (value, this);} public IStack <T> Pop (){ Throw new Exception ("Empty stack");} public IEnumerator <T> GetEnumerator () {yield break;} IEnumerator IEnumerable. getEnumerator () {return this. getEnumerator () ;}} private static readonly EmptyStack empty = new EmptyStack (); public static IStack <T> Empty {get {return empty;} private readonly T head; private readonly IStack <T> tail; private Stack (T head, IStack <T> tail) {this. head = head; This. tail = tail;} public bool IsEmpty {get {return false;} public T Peek () {return head;} public IStack <T> Pop () {return tail ;} public IStack <T> Push (T value) {return new Stack <T> (value, this);} public IEnumerator <T> GetEnumerator () {for (IStack <T> stack = this ;! Stack. IsEmpty; stack = stack. Pop () yield return stack. Peek ();} IEnumerator IEnumerable. GetEnumerator () {return this. GetEnumerator ();}}View Code
  • A new stack object will be instantiated during stack import.
  • Pass the new value through the constructor and place it at the Head position of the new object. The old stack object is referenced at the Tail position.
  • The stack object referenced by the Tail of the current stack object is returned when the stack is output.

The usage is as follows:

IStack<int> s1 = Stack<int>.Empty;IStack<int> s2 = s1.Push(10);IStack<int> s3 = s2.Push(20);IStack<int> s4 = s3.Push(30);IStack<int> v3 = s4.Pop();foreach (var item in s4){//dosomething}

Each Push is a new object and the old object cannot be modified. In this way, you do not need to worry about modifying other threads in the enumeration set.

Net-provided immutable set

The workload of data structures such as immutable queues and immutable lists is indeed huge if they are all implemented by themselves. Fortunately, the Net version 4.5 already provides a base class library for an unchangeable set. Install with Nuget:

Install-Package Microsoft.Bcl.Immutable

The usage is as follows:

        ImmutableStack<int> a1 = ImmutableStack<int>.Empty;        ImmutableStack<int> a2 = a1.Push(10);        ImmutableStack<int> a3 = a2.Push(20);        ImmutableStack<int> a4 = a3.Push(30);        ImmutableStack<int> iv3 = a4.Pop(); 

When using the Net immutable list set, note that it is correct to assign a value to the original variable when we Push the value, because a new object will be generated after the push, the original a1 is only the old value:

ImmutableStack <int> a1 = ImmutableStack <int>. Empty; a1.Push (10); // incorrect. a1 is still a null value and push generates a new stack. A1 = a1.Push (10); // you need to assign the new stack to A1.

Common data structures provided by NET

  • ImmutableStack
  • ImmutableQueue
  • ImmutableList
  • ImmutableHashSet
  • ImmutableSortedSet
  • ImmutableDictionary <K, V>
  • ImmutableSortedDictionary <K, V>

Immutable sets and variable sets differ in algorithm complexity:

Immutable advantages
  • Security of shared sets, never changed
  • No need to lock the set when accessing the Set (thread security)
  • Do not worry that the old set will be changed when you modify the set.
  • More concise writing, functional style. Var list = ImmutableList. Empty. Add (10). Add (20). Add (30 );
  • Ensure data integrity and security
Disadvantages of immutable objects

The disadvantage of immutable is that each object/set operation returns a new value. The old value will remain for a period of time, which will cause great memory overhead and GC recovery burden, and the performance is much worse than the variable set.

Like string and StringBuild, APIs for batch operations are added to the immutable set provided by Net to avoid creating a large number of objects:

ImmutableList <string> immutable = ImmutableList <string>. empty; // convert to the set var immutable2 = immutable. toBuilder (); immutable2.Add ("xx"); immutable2.Add ("xxx"); // restores it to an immutable set = immutable2.ToImmutable ();

We will compare the performance of the variable set, the variable Builder set, and the variable set, and add a new object times:

The comparison code is as follows:

Private static void List () {var list = new List <object> (); var sp = Stopwatch. startNew (); for (int I = 0; I <1000*10000; I ++) {var obj = new object (); list. add (obj);} Console. writeLine ("Variable list set:" + sp. elapsed);} private static void BuilderImmutableList () {var list = ImmutableList <object>. empty; var sp = Stopwatch. startNew (); var blist = list. toBuilder (); for (int I = 0; I <1000*10000; I ++) {var obj = new object (); blist. add (obj);} list = blist. toImmutable (); Console. writeLine ("unchangeable Builder list set:" + sp. elapsed);} private static void ImmutableList () {var list = ImmutableList <object>. empty; var sp = Stopwatch. startNew (); for (int I = 0; I <1000*10000; I ++) {var obj = new object (); list = list. add (obj);} Console. writeLine ("unchangeable list set:" + sp. elapsed );}View Code

Another disadvantage is interesting, and many others ignore it. Due to the immutable feature of string, we need to pay special attention when using string to save sensitive information.
For example, if the password is var pwd = "mushroomsir", the password will be stored in the memory in plain text. Maybe you will encrypt it later and set it to null, but this will generate new values. Plaintext is stored in the shared domain memory for a long time. Anyone who can get the dump file can see the plaintext, which increases the risk of password theft. Of course, this is not a new problem. net2.0 provides SecureString for secure storage and recovery and cleaning during use.

IntPtr addr = Marshal.SecureStringToBSTR(secureString);string temp = Marshal.PtrToStringBSTR(addr);Marshal.ZeroFreeBSTR(addr);WriteProcessMemory(...)

 

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.