33

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.

Paul Sasik
  • 79,492
  • 20
  • 149
  • 189

9 Answers9

18

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:

enter image description here

Zer0
  • 1,002
  • 1
  • 19
  • 40
18

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.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • 3
    @Jon: They are not supported in VB.NET, however. Just in C#. I reworded... sound better? – Reed Copsey Jun 30 '10 at 17:28
  • 3
    Yes, in an ideal world, we wouldn't have large methods that are difficult to refactor. But in the real world, we have 1000+ method bodies, and no budget to spend refactoring. Hence, it would be REALLY AWESOME if I could insert #regions in my vb.net code. Maybe I'll have to write a plugin... – mellamokb Nov 12 '10 at 18:03
  • 1
    @mellamokb: If you're working on the code that contains that large method body, I'd argue that time spent refactoring will **save time overall** when compared to adding functionality to the method and leaving it as-is. In addition to reducing technical debt, refactoring makes changing existing code easier, since it's much easier to verify that you don't break existing code when modifying a small method body vs. a large method body. Changing a huge method is incredibly problematic over time. – Reed Copsey Nov 12 '10 at 18:23
  • 4
    Reed Copsey - Don't really agree. I think code naturally defines its structure. Parts that are loosely coupled are great for pulling into methods with a few parameters, but if code sections which occur only once and are tightly coupled, ie would have many parameters if extracted, are extracted it can actually obscure the code to create methods for these. I use the regions all the time in c# to collapse sections of code and keep the structure clear, for any 'if' block or 'case' block longer than a screen. – Ben McIntyre Apr 23 '12 at 07:29
  • @Ben -- [StyleCop does agree with Reed](http://stylecop.soyuz5.com/SA1123.html) (though the reason I'm here is b/c I was looking for a good explanation of why SC dislikes it). – ruffin Jul 11 '13 at 02:45
16

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.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • 1
    my guess would be because #Region begins with a `#` character.. and VB allows you to specify a date by `#10/13/2009#`. – Sam Axe Feb 23 '14 at 09:38
  • hese directives are special in that they can neither start nor terminate within a method body <-- menas region directives, but not block directives like to collapse IF ELSE FOR NEXT.. – Devmyselz Nov 19 '22 at 23:11
12

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.

Cary Bondoc
  • 2,923
  • 4
  • 37
  • 60
  • 2
    +1 and re-selected as best answer. Thanks @Cary Bondoc: I added a note about your answer to the original question. – Paul Sasik Nov 24 '15 at 03:32
  • @PaulSasik thank you so much Sir for considering my answer, technology change so fast! :) – Cary Bondoc Nov 24 '15 at 11:14
  • 1
    For me, `#region` and `end region` are always moved to the beginning of the line (no indent like C# or like the code in your example).. can anyone confirm this? is there a workaround? because it's really annoying! – 41686d6564 stands w. Palestine Apr 19 '16 at 09:45
  • @GeniuSBraiN yeah, it seems that they are not indented like what you said. I've edited my answer. – Cary Bondoc Jun 16 '16 at 05:10
  • 2
    It works in visual studio, but building with msbuild on a separate build server fails even though it uses the same .net framework version for msbuild. [MSDN](https://msdn.microsoft.com/en-us/library/w96cy299.aspx) says it's not allowed for VS 2015 – Adam Mar 24 '17 at 09:50
10

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?

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
4

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.

JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
3

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
Community
  • 1
  • 1
Saragis
  • 1,782
  • 6
  • 21
  • 30
1

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.

AMissico
  • 21,470
  • 7
  • 78
  • 106
0

As someone struggling with this, I used the below solution since I don't have the option to upgrade the app while refactoring:

If 1 = 1 Then 'Region "some name" 'some code here End If

Then just collapse the if.