C # interesting parsing of local variable Declaration

Source: Internet
Author: User
Tags reflector
Let's take a look at the example of the exhibition:
Http://blog.joycode.com/zhanbos/archive/2004/10/26/36605.aspx
In this example, we can see that the compiler will check the scope problem to prevent incorrect use of local variables. But according to my research, there is a "bug" (pay attention to double quotation marks), so what is an interesting "bug? Let me give you a simple example:

Public   Void Test ()
{
{
IntA;
}
{
IntA;
}
}

There are two parentheses in the test function, which indicate two subscopes that do not belong to each other. You may not get used to it here, because no one writes these two pairs of braces. I told you: It doesn't matter. The Compiler acknowledges the bare braces. This is also one of the specifications in Standard C. It considers everything in braces as a "sentence ", to be accurate, it is a logical statement and a range is provided internally. Local variables within the scope of the constraint will not be transmitted outside. If you are not familiar with it, you can add a prefix such as while (true) to get used to it.
So this section Code What are the bugs? No, there are no bugs, and compilation passes smoothly. Of course, two warnings are displayed, indicating that A is not used and is harmless. First, let's analyze how the compiler passes this process? Let's look at it with reflector (of course, because there is no actual code, we can only look at Il, not C #): . Method Public Hidebysig instance Void Test () cel managed
{
//Code size: 2 byte (s)
. Maxstack0
. Locals(
Int32Num1,
Int32Num2)
L_0000: NOP
L_0001: Ret
}

 

Oh! The compiler changed the internal variable name! Or the compiler treats them as two completely different variables. At the same time, we can also see that, in fact, in Il, there is no difference in the scope, only a simple concept of local variables. No matter which range you are in and when to declare it, it is actually declared by a pseudo statement like. Locals at the beginning of the function. This is a simple and easy way to do this, because Source code Space is opened on the stack only when the actual declaration is made. When the function exits, it does not know how much stack space should be released. Of course this cannot be solved, but that increases unnecessary complexity. If I design the. NET Framework, I will also use the compiler of the advanced language to restrict the scope of the problem, instead of putting it in Il to solve it. (After all, the absence of such a function in Il does not affect our writing. Program ) A little more, we will know that the number of local variables in a function depends on the number of local variables declared in the function, regardless of the scope of the variable. At this layer of Il, we haven't seen such optimization work for the moment. We can see what the code is finally compiled by the compiler (compiled in release mode ): Public   Int Test ()
{
Int B;
B =   New Random (). Next ( 5 );
If (B <   5 )
{< br> int A = New random (). next ( 5 );
console. writeline (a);
B = A;
}
Else
{< br> int A = New random (). next ( 10 );
console. writeline (a);
B = A;
}
Return B;
}

Reflector decompilation result: Public   Int Test ()
{
Int Num1 =   New Random (). Next ( 5 );
If (Num1 <   5 )
{
IntNum2= NewRandom (). Next (5);
Console. writeline (num2 );
ReturnNum2;
}
Int Num3 =   New Random (). Next ( 10 );
Console. writeline (num3 );
Return Num3;
}

We can see that num1 is B, and num2 and num3 are two separate. In fact, there is no conflict between the two A, that is, they can be completely reused. There is also a variable reuse optimization in the compilation principle, but there is no such optimization here, I was surprised. Although this can be regarded as a bug (strictly speaking, it is not), the "bug" I want to talk about is not.

After analyzing the above basic knowledge, I will try again: Public   Void Test ()
{
{
IntA;
}
{
IntA;
}
Int A;
}

After compilation, an error occurs:
Error cs0136: A local variable named 'A' cannot be declared in this scope because it wocould give a different meaning to 'A ', which is already used in a 'child 'scope to denote something else
Oh, it turns out that this has nothing to do with the declared sequence. As long as there is a in the subrange, this variable cannot be defined. Is this related to the partial declaration of all variables in Il at the beginning of the function? It seems to be the same thing, but it is not actually because the C # compiler can treat the last a as another variable just like the previous one. What the hell is going on? We need to make the last experiment of this exploration: Public   Void Test ()
{
A =   2 ;
{
IntA;
}
{
IntA;
}
Int A;
}

This is good. In addition to the error just now, there is another one:
Error cs0103: The name 'A' does not exist in the class or namespace 'leleapplication1. class2'
That is to say, the compiler does not regard the subsequent A as defined from the beginning of the function. However, the combination of these two errors may lead to the illusion and paradox:
Because the influence of the first two A should disappear outside the scope, it should not conflict with the latter. But now, as you have said, one of the first two of the three definitions of A is in conflict, then I can only think that the next a actually exists before the first two A are defined, because the next a is in the outer range, and it will not expire before the inner range becomes ineffective, this can be explained. However, I can only think that the outer A should take effect in the beginning of the function (the old-fashioned C compiler does for a while ), but a cs0103 error is returned! There is a bug "!

In the end, I fixed this statement at the beginning. In fact, there is no bug. I came to the conclusion that there was a bug. From the perspective of pure syntax, I also felt that the definition of the third A should be allowed. At most, only one warning should be given. However, Microsoft gave an error. I think this is to avoid unnecessary bugs and try to protect developers from unnecessary troubles. It is very likely that the developer forgets that the first and second A have expired when defining the third A, and also forgets that he has defined the third, I thought I was using the data in the first or second. However, I still have some opinions on this explanation: Since the constraints have been reduced to this point, why should we allow the definition of the second? If developers forget to define the third A, why do they think they will not forget the definition of the second A and think they are using the first?

All of the above are spam code. I think there should be no Identical variables in a function to confuse myself. The C # compiler does have a very rigorous consideration in these aspects, but I still think there are some "Paradox". If it is more rigorous, I think it will be better.

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.