[C #. Tips] also talks about interface fraud

Source: Internet
Author: User
I have to explain that this is another article related to value-type packing and unpacking, although I have recently written two articles to explain this basic problem. They are here and here respectively. The sample code in this article comes from the latter and is slightly modified.
We know that C # Is a "secure" language, so that it does not allow us to modify the fields in the boxed Value Type instance. This will bring unexpected results. The following explains why this "unexpected" situation occurs for many programmers and how to "cheat" C # to realize the true intent of the programmer, although it is not a reasonable way.
First, I will refer to the old code I mentioned here:

1/** // <summary>
2 // The ticket re-booking Interface
3 /// </Summary>
4 Internal interface irebook
5 {
6 ticket rebook (string newterminal, int32 newdistance );
7}
8
9 internal struct Ticket: irebook
10 {
11 private string _ start, _ terminal; // start and end
12 private int32 _ distance; // distance
13
14 public ticket (string start, String Terminal, int32 distance)
15 {
16 _ start = start;
17 _ terminal = terminal;
18 _ distance = distance;
19}
20
21
22/*** // <summary>
23 // override the tostring method of system. valuetype
24 /// </Summary>
25 public override string tostring ()
26 {
27 return string. Format ("from {0} to {1}, {2} km ",
28 _ start,
29 _ terminal,
30 _ distance); // inside the method, _ distance is boxed
31}
32
33 irebook members # region irebook members
34/*** // <summary>
35 // re-book tickets
36 /// </Summary>
37 // <Param name = "newterminal"> New Terminal </param>
38 // <Param name = "newdistance"> distance from the terminal </param>
39 public ticket rebook (string newterminal, int newdistance)
40 {
41 _ terminal = newterminal;
42 _ distance = newdistance;
43 return this;
44}
45
46 # endregion
47}
48
49 public sealed class Program
50 {
51 public static void main ()
52 {
53 ticket T = new ticket ("Beijing", "Hankou", 1225 );
54 // Value Type instance t is packed here for the first time: ticket --> Object --> override tostring
55 console. writeline (t );
56
57 // boxed display
58 // console. writeline (object) T). tostring ());
59
60 TB. rebook ("Shanghai", 1400 );
61 console. writeline (t );
62
63 object o = T;
64 console. writeline (O );
65
66 ticket t2 = (ticket) O). rebook ("Guangzhou", 2000 );
67 console. writeline (O );
68 console. writeline (T2 );
69
70 // t --> irebook, boxed
71 (irebook) T). rebook ("Guangzhou", 2000 );
72 console. writeline (t );
73
74 // o --> irebook, no need to pack
75 (irebook) O). rebook ("Guangzhou", 2000 );
76 console. writeline (O );
77}
78}

Compared with the previous Code, only one interface irebook is added, and this interface is implemented in ticket. In terms of output, the first five outputs are the same as the original code, and the results are also displayed. I have added two outputs at the end. You can first guess what the output result will be like in line 1?
It seems that our original intention was to change the ticket to Guangzhou at 2000 km. However, the output here is still "from Beijing to Shanghai, 1400 km ". This is against our original intention (in fact, it is unreasonable to define such a method ).

What causes the change to fail? A friend who has read this article can see that, because the value type instance t is boxed into the reference type irebook, when we call the rebook, only the boxed Value Type instances (tii) generated by CLR are modified. Because there is no reference pointing to tii, tii will be identified and recycled by GC.

So how can we make this change to the value type instance field reasonable? This is why the interface is introduced. In the 75th rows, we transformed the reference type O (which points to the boxed Value Type tii) into irebook, which is a conversion between two reference types, there is no packing or unpacking and no additional copies are created. Therefore, when we call the rebook method on the irebook, the changed result "from Beijing to Guangzhou, 2000 km" will be displayed ".
This is called interface fraud, which indirectly modifies the instance fields of the boxed value type.
The complete output result of the program is as follows:
Obviously, a mutable value type, such as ticket, is generally unreasonable because it will bring us unexpected results like the above, in addition, it will produce additional "garbage", which should be noted when we define any value type. In this example, it is better to clearly define ticket as a class, because it avoids generating "out-of-control objects" and its operations.

In short, "a value type member should not modify any instance field" -- CLR via C #.
By the way, let's talk about interfaces. Generally, do not convert unboxed value types to interface types, this is because it actually allows the CLR to "quietly" Create a boxed Value Type behind the scenes, but you cannot control it.

Let's write it here. I always hope to clarify the problem in the simplest words. I also welcome criticism and correction.

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.