# region / # endregion vs sub functions?

How do you recommend using # region / # endregion? To what extent should you replace using helper functions to refine your code?

+2


source to share


6 answers


Not at all.

First of all, #regions

it is more of a way of grouping many related functions / members into collapsible regions. They are not intended to structure one multi-thousandth linear function into parts. (If you write one method that's so long that you plan to structure it with #region

, then you are probably doing something seriously wrong. Regions or not, this code will be unreachable. Period.)



Many people argue, however, that this really doesn't help, and that you should consider rewriting the classes that really need regions to be understood. In addition, regions tend to hide nasty code.

+22


source


#region

/ #endregion

is a way to logically group pieces of code that belong to the same class. Personally, I tend to group private field declarations, properties, public functions, and private functions.



Sometimes I use these keywords to group together some parts of the code that I need to look after and update frequently, such as calculation methods.

+3


source


If your class has more than a "logical grouping of code", your class violates the single responsibility principle.

Sorting and you don't need regions anymore.

0


source


Regions seem good in theory, but in my experience this is a feature that is often overused.

Programmers love order; most people like to put things away in small boxes. They group messy code, fields, properties, constructors, methods, public methods, internal methods, private methods, helper methods, constants, interface implementations, and God knows what else.

The only thing I can think of that annoys me more is using partial classes to hide the complexity.

Anyway, while overuse of regions is often a telltale sign of hiding clutter that shouldn't be there, I've also seen good code littered with them. I have uploaded several open source projects written by reputable programmers. These guys are writing some awesome code, but oh, what is it?

One field? Field area! Two properties? Property region! One constructor? Constructor area! One private method? Private method area!

I could go on.

On the same day, I am still amazed when I see this. In some cases, the area, blank line, other blank line, and trailing area can take up 5 times the space of the source code (5 lines with areas, 1 line without). It's basically a form of OCD; these regions may attract our sense of order when writing software, but in practice they are useless - pure noise. When I first started writing C #, I overused them too. But then I realized how noisy my code was, and that pressing ctrl-k l every time I open a file is a sign that I was doing it wrong.

I can figure it out when a class implements an interface that has many properties (like for data binding) or even a bunch of methods to implement some related functionality, but for everything ?. It doesn't make any sense.

I still use regions from time to time, but ... I am showing great restraint.

0


source


The only circumstance I ever saw where I felt in the region was entirely in the code below. Once I figured it out, I never wanted to look at these constants again. In fact, I use this class every day, and I think the only time I lost this region in the last four years was that I had to redefine it in Python.

I think (hope, pray) that the circumstances of this code are edge case. C # constants, based on the VB3 type declaration, which defines how the COBOL data structure returned by a C ++ function is laid out. Yes, I put this in Python. I'm so good. I'm tempted to learn Haskell just so that I can rewrite my Python code in it, taking a look at one day overriding my Haskell code in OCaml.

    #region buffer_definition
    /*
        The buffer is a byte array that is passed to the underlying API.  The VB representation of
        the buffer structure (using zero-based arrays, so each array has one more element than
        its dimension) is this:

        Public Type BUFFER_TYPE
            Method As String * 50
            Status As Integer
            Msg As String * 200
            DataLine As String * 1200

            Prop(49) As String * 100

            Fld(79) As String * 20
            Fmt(79) As String * 50
            Prompt(79) As String * 20
            ValIn(79) As String * 80
            ValOut(79) As String * 80
        End Type

        The constants defined here have the following prefixes:
            len = field length
            cnt = count of fields in an array
            ptr = starting position within the buffer
    */

    // data element lengths
    private const int len_method = 50;
    private const int len_status = 2;
    private const int len_msg = 200;
    private const int len_dataLine = 1200;

    // array elements require both count and length:
    private const int cnt_prop = 50;
    private const int len_prop = 100;

    private const int cnt_fld = 80;
    private const int len_fld = 20;
    private const int len_fmt = 50;
    private const int len_prompt = 20;
    private const int len_valIn = 80;
    private const int len_valOut = 80;

    // calculate the buffer length
    private const int len_buffer =
        len_method
        + len_status
        + len_msg
        + len_dataLine
        + (cnt_prop * len_prop)
        + (cnt_fld * (len_fld + len_fmt + len_prompt + len_valIn + len_valOut));

    // calculate the pointers to the start of each field.  These pointers are used
    // in the marshalling methods to marshal data into and out of the buffer.
    private const int PtrMethod = 0;
    private const int PtrStatus = PtrMethod + len_method;
    private const int PtrMsg = PtrStatus + len_status;
    private const int PtrDataLine = PtrMsg + len_msg;
    private const int PtrProp = PtrDataLine + len_dataLine;
    private const int PtrFld = PtrProp + (cnt_prop * len_prop);
    private const int PtrFmt = PtrFld + (cnt_fld * len_fld);
    private const int PtrPrompt = PtrFmt + (cnt_fld * len_fmt);
    private const int PtrValIn = PtrPrompt + (cnt_fld * len_prompt);
    private const int PtrValOut = PtrValIn + (cnt_fld * len_valIn);

    [MarshalAs(UnmanagedType.LPStr, SizeConst = len_buffer)]
    private static byte[] buffer = new byte[len_buffer];

    #endregion

      

0


source


I think functions should only be used for reusable code. What they are for. Nothing stops me more than seeing that a function is being created for something that is called only once.

Use the area.

If you need to do 500 lines, enter 500 lines. If you want to use the area neatly, if there is something reusable, use the function.

0


source







All Articles