Code regions not allowed within method bodies in V

2019-04-17 21:11发布

问题:

Note: This "feature" has now been added to Visual Studio 2015 but the question will hold a while since not every developer or every dev shop gets access to the latest and greatest IDE as soon as it comes out.

ORIGINAL QUESTION:

Normally I wouldn't "need" or even consider a ridiculous feature such as code regions within method bodies but: I'm refactoring VB.NET code where methods routinely run five hundred lines of code or more and the references are so tightly coupled that the code defies simple refactoring such as method extraction.

And that's why I thought I would try regions within a method body. I just wanted to organize the code for the short term. But the IDE doesn't let me (resulted in a compiler error.) I'm just curious as to why? Seems like code regions shouldn't impact the compiler, intellisense etc. Am I missing something? (Still using VS 2005 btw.)

Interesting: This seems to be language specific. It's OK in C# (I didn't check that initially) but not in VB.NET.

public module MyModule
    Sub RunSnippet()
        dim a as A = new A (Int32.MaxValue )

        #region 
        Console.WriteLine ("")
        #end region
       ....

that gets a compiler error but the C# version is ok.

回答1:

As of November 2015: In Visual Studio 2015 it is now supported, just do what you like.

Sample Code:

With frmMain
#region "A sample region in odd place"
  .show()
  .text = "Sample"
#end region
End With

Note: In earlier versions of Visual Studio it seems that it is not working in VB.NET, but in C# it is working.



回答2:

I think code regions probably wouldn't be supported in method bodies since they, as you put it, would be a (somewhat) "ridiculous feature" - However, in C#, this does work, at least in VS 2008 and VS 2010 - just not in VB.NET.

That being said, I would avoid it. Putting regions within a method body would just leads to people making larger methods (since that's the only time when it would be worthwhile), which is something that should be avoided, not encouraged.

If your code:

defies simple refactoring such as method extraction

I would focus, instead, on doing "complex" refactoring (or whatever it takes) to try to break up those methods. There is no way your "four or five hundred lines" long methods are at all maintainable in their current state.

Personally, I would leave them causing "pain" - make it obvious that they need work, right front and center, until you can break them up and refactor out portions.



回答3:

It is explicit in chapter 3.3 of the Visual Basic 9.0 Language Specification:

Region directives group lines of source code but have no other effect on compilation. The entire group can be collapsed and hidden, or expanded and viewed, in the integrated development environment (IDE). These directives are special in that they can neither start nor terminate within a method body

Or in other words: you cannot do it because the specification says so.

As to why it was specified like this, I reckon it has something to do with the age-old IDE feature that VB has had for as long as I can remember: Tools + Options, Text Editor, Basic, VB Specific, Show procedure line separators. That's just a guess, probably not a very good one.


Update: now supported by Roslyn, included first with VS2015.



回答4:

Another simple alternative method:

What you can do is basically select the code you want to add the #Region #End Region and basically click:

Ctrl+M, Ctrl+H

This basically wraps the code. And then to make it even neater and easy to find you can comment the code. The end result would look something like this:



回答5:

I don't know about VB, but in C# this has been allowed since 1.0 as far as I'm aware.

Indeed, you can even put code regions in odd places which cross scopes. For example:

class Test
{
    static void Main()
    {
        if (DateTime.Now.Hour > 12)
        {
#region Foo
            Console.WriteLine("Afternoon");            
        }
#endregion
    }
}

Here the region starts within the if statement, but ends outside it. Horrible, but the compiler is fine with it.

What do you mean when you said the IDE didn't "let" you put code in regions? Did you get a compiler error?



回答6:

This was simply a choice the VB team made when adding the regions feature into version 7 of the Visual Basic language. It was seen as a feature which was useful for organizing at a declaration level and not inside a method and hence was allowed only at that level.

The C# team felt differently about this feature and allow it in many other places. I've always found it surprising that C# #region directives can occur in different declaration contexts.

#region Foo
class Bar {
#endregion

}

The equivalent code is not allowed in VB.



回答7:

For anyone looking for the most recent answer to this question, this is now possible in VB.NET (starting from version 14 on).

Region Directives inside Method Bodies

You can put #Region…#End Region delimiters anywhere in a file, inside functions, and even spanning across function bodies.

The example from the OP is now perfectly legal syntax:

Sub RunSnippet()
    Dim a as A = New A (Int32.MaxValue )

    #Region "Test"
    Console.WriteLine ("")
    #End Region
End Sub


回答8:

Visual Studio 2003 had them for VB.NET, but feature was removed in Visual Studio 2005 and later. Really annoying when refactoring large procedures, yet you can split the code window.

Honestly, I wish C# would restrict region use because they are overly used. I have a macro that strips them out of all code files when inheriting C# projects.

Another feature removed was the list of overridable methods in the Navigation Bar. I check to see if they re-added this feature for every new version of Visual Studio since 2005.