Advantages of using const instead of variables inside methods

后端 未结 8 893
北恋
北恋 2020-12-02 16:09

Whenever I have local variables in a method, ReSharper suggests to convert them to constants:

// instead of this:
var s = \"some string\";
var flags = Bindin         


        
相关标签:
8条回答
  • 2020-12-02 16:49

    Besides the small performance improvement, when you declare a constant you are explicitly enforcing two rules on yourself and other developers who will use your code

    1. I have to initialize it with a value right now i can't to do it any place else.
    2. I cannot change its value anywhere.

    In code its all about readability and communication.

    0 讨论(0)
  • 2020-12-02 16:51

    tl;dr for local variables with literal values, const makes no difference at all.


    Your distinction of "inside methods" is very important. Let's look at it, then compare it with const fields.

    Const local variables

    The only benefit of a const local variable is that the value cannot be reassigned.

    However const is limited to primitive types (int, double, ...) and string, which limits its applicability.

    Digression: There are proposals for the C# compiler to allow a more general concept of 'readonly' locals (here) which would extend this benefit to other scenarios. They will probably not be thought of as const though, and would likely have a different keyword for such declarations (i.e. let or readonly var or something like that).

    Consider these two methods:

    private static string LocalVarString()
    {
        var s = "hello";
        return s;
    }
    
    private static string LocalConstString()
    {
        const string s = "hello";
        return s;
    }
    

    Built in Release mode we see the following (abridged) IL:

    .method private hidebysig static string LocalVarString() cil managed 
    {
        ldstr        "hello"
        ret          
    }
    
    .method private hidebysig static string LocalConstString() cil managed 
    {
        ldstr        "hello"
        ret          
    }
    

    As you can see, they both produce the exact same IL. Whether the local s is const or not has no impact.

    The same is true for primitive types. Here's an example using int:

    private static int LocalVarInt()
    {
        var i = 1234;
        return i;
    }
    
    private static int LocalConstInt()
    {
        const int i = 1234;
        return i;
    }
    

    And again, the IL:

    .method private hidebysig static int32 LocalVarInt() cil managed
    {
        ldc.i4       1234
        ret          
    }
    
    .method private hidebysig static int32 LocalConstInt() cil managed
    {
        ldc.i4       1234
        ret     
    }
    

    So again we see no difference. There cannot be a performance or memory difference here. The only difference is that the developer cannot re-assign the symbol.

    Const fields

    Comparing a const field with a variable field is different. A non-const field must be read at runtime. So you end up with IL like this:

    // Load a const field
    ldc.i4       1234
    
    // Load a non-const field
    ldsfld       int32 MyProject.MyClass::_myInt
    

    It's clear to see how this could result in a performance difference, assuming the JIT cannot inline a constant value itself.

    Another important difference here is for public const fields that are shared across assemblies. If one assembly exposes a const field, and another uses it, then the actual value of that field is copied at compile time. This means that if the assembly containing the const field is updated but the using assembly is not re-compiled, then the old (and possibly incorrect) value will be used.

    Const expressions

    Consider these two declarations:

    const int i = 1 + 2;
    int i = 1 + 2;
    

    For the const form, the addition must be computed at compile time, meaning the number 3 is kept in the IL.

    For the non-const form, the compiler is free to emit the addition operation in the IL, though the JIT would almost certainly apply a basic constant folding optimisation so the generated machine code would be identical.

    The C# 7.3 compiler emits the ldc.i4.3 opcode for both of the above expressions.

    0 讨论(0)
  • 2020-12-02 16:52

    As per my understanding Const values do not exist at run time - i.e. in form of a variable stored in some memory location - they are embeded in MSIL code at compile time . And hence would have an impact on performance. More over run-time would not be required to perform any house keeping (conversion checks / garbage collection etc) on them as well, where as variables require these checks.

    0 讨论(0)
  • 2020-12-02 16:52

    A const value is also 'shared' between all instances of an object. It could result in lower memory usage as well.

    As an example:

    public class NonStatic
    {
        int one = 1;
        int two = 2;
        int three = 3;
        int four = 4;
        int five = 5;
        int six = 6;
        int seven = 7;
        int eight = 8;
        int nine = 9;
        int ten = 10;        
    }
    
    public class Static
    {
        static int one = 1;
        static int two = 2;
        static int three = 3;
        static int four = 4;
        static int five = 5;
        static int six = 6;
        static int seven = 7;
        static int eight = 8;
        static int nine = 9;
        static int ten = 10;
    }
    

    Memory consumption is tricky in .Net and I won't pretend to understand the finer details of it, but if you instantiate a list with a million 'Static' it is likely to use considerably less memory than if you do not.

        static void Main(string[] args)
        {
            var maxSize = 1000000;
            var items = new List<NonStatic>();
            //var items = new List<Static>();
    
            for (var i=0;i<maxSize;i++)
            {
                items.Add(new NonStatic());
                //items.Add(new Static());
            }
    
            Console.WriteLine(System.Diagnostics.Process.GetCurrentProcess().WorkingSet64);
            Console.Read();
        }
    

    When using 'NonStatic' the working set is 69,398,528 compared to only 32,423,936 when using static.

    0 讨论(0)
  • 2020-12-02 17:07

    The const keyword tells the compiler that it can be fully evaluated at compile time. There is a performance & memory advantage to this, but it is small.

    0 讨论(0)
  • 2020-12-02 17:11

    const is a compile time constant - that means all your code that is using the const variable is compiled to contain the constant expression the const variable contains - the emitted IL will contain that constant value itself.

    This means the memory footprint is smaller for your method because the constant does not require any memory to be allocated at runtime.

    0 讨论(0)
提交回复
热议问题