Hahaha, indeed. I didn't realize myself until I started looking into this that MS named the system in Vista the same as the Apple team did in Panther. :) Guess it is the nerd in us all wanting to be working on the "Core" stuff
The code is well structured and easy to read. Thanks for the example.
Random aside: Why do so many C# coders use #region/#endregion? It really seems like a bad habit that discourages otherwise good coders from splitting their code into logical OOP silos and instead they dump too much code into a single file, and then use regions to regain some kind of order...
Regions are like goto in that they don't within their own right do anything "bad" they just encourage really bad habits, and people start to think about things in terms of regions. Plus finding things in a project which contains tons of really long code files with regions is immensely harder than finding them in a project with a lot of isolated classes and decent inheritance.
I don't get C# regions, either. At least Visual Studio makes it easy to auto-expand them and effectively ignore them while jumping around with incremental search and goto definition. Admittedly, this would be a problem if the rest of the team cared about maintaining the regions.
I admit that sometimes I find them handy to use when dealing with large complex files. Grouping together member variables, events, statics can help with reducing the initial noise when opening the file (these tend to be at the top of the class usually).
But they indeed depend on the team's total commitment on keeping them organized and up-to-date.
Thanks for the kind words :)
Yeah regions are a strange beast in C#. In some cases I find them handy, like in this instance where I wanted the COM interfaces embedded in the main class file. Also to clearly separate which functions belong to the manipulation of master vs individual program audio levels.
The region paradigm is very often misused and is one of those things that starts off nice and then degrades as time goes on (meaning new functions get added in the wrong region, refactorings end up all over the place, etc). I prefer them though over partial classes (shudder) and when properly used they can be a huge timesaver when dealing with those annoying UBER-Forms that tend to happen when dealing with legacy WinForms code :)
From sibling post:
> when dealing with those annoying UBER-Forms that tend to happen when dealing with legacy WinForms code :)
This is similar to my experience.
I use regions pretty often when I'm refactoring overgrown legacy code, especially older MVC apps (where the controllers get insane)
Basically what you said, but reversed. I use regions as a first step to regaining some kind of order, then continue to pull things apart into more properly factored classes, methods, etc. It helps me mentally map things out. Of course there're a bunch of ways you could do that, but Visual Studio has good support for folding regions, so I prefer it.
That folding is the second reason I'll use them sometimes. If I have a really awkward part of code that I'd like to fold for whatever reason, I'll occasionally use them if I think it'll make things more readable.
I agree with the idea, though. Every time I use a region I have to stop and think "am I just hiding bad design?"
I hear you. Seven year old MVC forms with five pages of inputs, backed up to a single forty column table via Entity Framework, and a controller with another five pages of arcane conditionals for binding and validations :|
I think regions are super useful. Even within the context of a class, I create regions for various types of code, e.g., constructors, private fields, etc...
I'm not sure how regions change how you create your class hierarchies and such. One of the first things I do when I inherit a project, is I add regions to it. I'm not changing the class hierarchies, but I am making it a lot easier to navigate within Visual Studio.
I don't see how hiding large chunks of code behind a drop-down is making it "easier to navigate in Visual Studio." If anything it is now much harder.
Plus you're now burying how long your class is and the individual methods within. So a class or method that would otherwise be inappropriately long now looks a reasonable length.
If you feel like the code is so long that it needs regions, then refactor the code, don't hide the mess under the bed.
I can't speak for the gp, but they were talking about inheriting a project/legacy code.
If I end up needing to go through legacy code, and there are a lot of gnarly, long methods/blocks, I'll usually add comments and regions to it as I go along. I'll use comments if I just want to note something, and a region if I want to note something about a region of code. It's my rough map. Being able to tell Visual Studio to arbitrarily collapse an area is handy for sketching it. The long term goal is to refactor, but it's handy as a way to quickly outline things.
Ugh. Every time I inherit code that someone has peppered with regions, I delete then. It's a bunch of extra noise if you expand all regions, and if they're collapsed it's harder to see the overall structure of the code, and some functionality (specifically undo/redo, but others also) gets gimpy when collapsed regions are involved, making it hard to see what is changing.
I find regions to be useful 1% of the time, simply pointless 10% of the time, and hiding crappy code the other 89% of the time. When I open up code and see a bunch of regions, I immediately assume that the file contains way too much unrelated functionality and that the code is poorly written. This assumption is very rarely wrong.
> discourages ... from splitting their code into logical OOP silos
What you fail to see is those silos can be a prison. One of the worst experiences I consistently have with heavily "OOP-person" code is you come to a new source tree and there are so many little tiny do-nothing classes and interfaces in individually tiny insignificant files that you can't come fresh to the project and tell "where the meat is" by browsing the filesystem. Putting those smaller interfaces and glue in a few mid-sized thematically oriented source files can be a breath of fresh air relative to this.
Exactly this. There is a fine line with regions and they have their uses.
As an example, I was working on a project a while back that had StyleCop rules set up so stringently that nothing could live in the same file, no enums, structs, extension methods, nada. The amount of files you had to create when adding new functionality (even a minor one) was mind boggling...
I feel like in languages like this you shouldn't even be using filesystem to browse the code but jump in to IDE visualization tools (hopefully there are architectural docs with this stuff outlined, but if not I just look at stuff like class diagrams)
My experience with C# and Java agrees with you completely. As someone who didn't start with, and never quite understood, the OOP craze, the urge to make tiny pieces that have almost nothing in them is baffling. Arguments that it's "more readable" are true only locally, and understanding a single-line method does nothing for understanding the system as a whole; a significantly larger amount of cross-file jumping (and often keeping track of a very deep the call stack) is a hindrance. I suppose they do this because it gives the feeling and appearance of being highly productive, when they're really just making things more difficult for themselves and others by bloating the complexity.
The other annoyance that I often encounter at the same time is terribly long and redundant variable names, accompanied by an overdose of design patterns. ("Was it the FooFactoryInterfaceAdapterList or the FooFactoryInterfaceList that particular method was in?") An example from this article's code is GetMasterVolume() vs. GetMasterVolumeMute() --- GetMasterMute() is just as descriptive, especially when the class is already named AudioManager. There's no GetApplicationVolumeMute(), instead it nicely appears as the more succinct GetApplicationMute().
I know there are IDEs which will help you go to the right file, but it's still not as easy as just scrolling through a larger one and reading linearly. That said, excessive code duplication is to be avoided and best replaced with a function; the code referenced in this article shows signs of that, as I easily saw this fragment repeated many times, among others:
ISimpleAudioVolume volume = GetVolumeObject(pid);
if (volume == null)
return;
It made me rethink a few of the ways I've used regions previously. As a stopgap for refactoring legacy code, though, I'm still not 100% sold.
Like a lot of articles here, the comments and the back and forth are as interesting as the answer. I think right now I'd say that, used carefully, there's nothing implicitly wrong with regions, but overall it's probably better to avoid them. Honestly, I'll probably have to do a little more digging and see where it comes out.
They're reminding me of comments in general at this point, where there's nothing implicitly wrong with them, but every time you write one you should be asking yourself if you could clearly bake that intention/information into the code itself.
I only use regions to categorize old/legacy code that either is going to be pulled into its own class or outright replaced with a much better implementation. I don't like to use regions since VS already makes it relatively easy to navigate to a method.
Holy shit, thank you. I wrote a tool to mute a game automatically when I backgrounded the window and was extremely annoyed when I found out that I had to work with COM in C++. I knew absolutely 0 COM and had to clobber together example code until I got something that barely worked and crashed randomly. I figured C# had good COM integration and could do it but just couldn't quite figure out how.
29 comments
[ 2.7 ms ] story [ 73.9 ms ] threadTurns out a bit of a disappointment for the hacker in me. Windows has an API with the same name (https://msdn.microsoft.com/en-us/library/windows/desktop/dd3...)
Random aside: Why do so many C# coders use #region/#endregion? It really seems like a bad habit that discourages otherwise good coders from splitting their code into logical OOP silos and instead they dump too much code into a single file, and then use regions to regain some kind of order...
Regions are like goto in that they don't within their own right do anything "bad" they just encourage really bad habits, and people start to think about things in terms of regions. Plus finding things in a project which contains tons of really long code files with regions is immensely harder than finding them in a project with a lot of isolated classes and decent inheritance.
But they indeed depend on the team's total commitment on keeping them organized and up-to-date.
The region paradigm is very often misused and is one of those things that starts off nice and then degrades as time goes on (meaning new functions get added in the wrong region, refactorings end up all over the place, etc). I prefer them though over partial classes (shudder) and when properly used they can be a huge timesaver when dealing with those annoying UBER-Forms that tend to happen when dealing with legacy WinForms code :)
This is similar to my experience.
I use regions pretty often when I'm refactoring overgrown legacy code, especially older MVC apps (where the controllers get insane)
Basically what you said, but reversed. I use regions as a first step to regaining some kind of order, then continue to pull things apart into more properly factored classes, methods, etc. It helps me mentally map things out. Of course there're a bunch of ways you could do that, but Visual Studio has good support for folding regions, so I prefer it.
That folding is the second reason I'll use them sometimes. If I have a really awkward part of code that I'd like to fold for whatever reason, I'll occasionally use them if I think it'll make things more readable.
I agree with the idea, though. Every time I use a region I have to stop and think "am I just hiding bad design?"
Oh dear lord the MVC madness I've seen... thousand yard stare
I'm not sure how regions change how you create your class hierarchies and such. One of the first things I do when I inherit a project, is I add regions to it. I'm not changing the class hierarchies, but I am making it a lot easier to navigate within Visual Studio.
Plus you're now burying how long your class is and the individual methods within. So a class or method that would otherwise be inappropriately long now looks a reasonable length.
If you feel like the code is so long that it needs regions, then refactor the code, don't hide the mess under the bed.
If I end up needing to go through legacy code, and there are a lot of gnarly, long methods/blocks, I'll usually add comments and regions to it as I go along. I'll use comments if I just want to note something, and a region if I want to note something about a region of code. It's my rough map. Being able to tell Visual Studio to arbitrarily collapse an area is handy for sketching it. The long term goal is to refactor, but it's handy as a way to quickly outline things.
I find regions to be useful 1% of the time, simply pointless 10% of the time, and hiding crappy code the other 89% of the time. When I open up code and see a bunch of regions, I immediately assume that the file contains way too much unrelated functionality and that the code is poorly written. This assumption is very rarely wrong.
What you fail to see is those silos can be a prison. One of the worst experiences I consistently have with heavily "OOP-person" code is you come to a new source tree and there are so many little tiny do-nothing classes and interfaces in individually tiny insignificant files that you can't come fresh to the project and tell "where the meat is" by browsing the filesystem. Putting those smaller interfaces and glue in a few mid-sized thematically oriented source files can be a breath of fresh air relative to this.
As an example, I was working on a project a while back that had StyleCop rules set up so stringently that nothing could live in the same file, no enums, structs, extension methods, nada. The amount of files you had to create when adding new functionality (even a minor one) was mind boggling...
The other annoyance that I often encounter at the same time is terribly long and redundant variable names, accompanied by an overdose of design patterns. ("Was it the FooFactoryInterfaceAdapterList or the FooFactoryInterfaceList that particular method was in?") An example from this article's code is GetMasterVolume() vs. GetMasterVolumeMute() --- GetMasterMute() is just as descriptive, especially when the class is already named AudioManager. There's no GetApplicationVolumeMute(), instead it nicely appears as the more succinct GetApplicationMute().
I know there are IDEs which will help you go to the right file, but it's still not as easy as just scrolling through a larger one and reading linearly. That said, excessive code duplication is to be avoided and best replaced with a function; the code referenced in this article shows signs of that, as I easily saw this fragment repeated many times, among others:
It made me rethink a few of the ways I've used regions previously. As a stopgap for refactoring legacy code, though, I'm still not 100% sold.
Like a lot of articles here, the comments and the back and forth are as interesting as the answer. I think right now I'd say that, used carefully, there's nothing implicitly wrong with regions, but overall it's probably better to avoid them. Honestly, I'll probably have to do a little more digging and see where it comes out.
They're reminding me of comments in general at this point, where there's nothing implicitly wrong with them, but every time you write one you should be asking yourself if you could clearly bake that intention/information into the code itself.
I also don't like it.
It gets even worse when the solutions are configured to collapse regions by default.
Also Apple is doing the same with regions for Objective-C and Swift.
https://msdn.microsoft.com/en-us/library/windows/hardware/mt...