Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the usage of private static method in c#?

I have a public class called MyClass.cs. It has 3 methods:

 public class MyClass
 {
    public IEnumerable<MyDto> PublicA(bool useCache = true)
    {
    //Call an external resource
    //some code
    }

    public IEnumerable<AnotherDto> PublicB()
    {
    //some code
    var x= MyPrivateMethod(input);
    //some code
    }

    private IEnumerable<AnotherDto> MyPrivateMethod(IEnumerable<SomeDto>)
    {
    //return Mapped data from IEnumerable<SomeDto> to  IEnumerable<AnotherDto>

    }
 }

I use ReSharper as a refactoring tool. It suggests using static for MyPrivateMethod.

private static IEnumerable<AnotherDto> MyPrivateMethod(IEnumerable<SomeDto>)

But what is the usage of this keyword, here? Since the method is private and will not be used in other class that want to use an instance of MyClass.

I tested and found out that, when I use the static keyword for MyPrivateMethod, I can not call any other methods of the class that are NOT private static. But yet I don't know what is the usage? Is there any benefit on storage or time optimization, for example?

like image 586
Elnaz Avatar asked Dec 18 '22 01:12

Elnaz


1 Answers

As per MSDN

Members that do not access instance data or call instance methods can be marked as static (Shared in Visual Basic). After you mark the methods as static, the compiler will emit nonvirtual call sites to these members. Emitting nonvirtual call sites will prevent a check at runtime for each call that makes sure that the current object pointer is non-null. This can achieve a measurable performance gain for performance-sensitive code. In some cases, the failure to access the current object instance represents a correctness issue.

https://msdn.microsoft.com/en-us/library/ms245046.aspx

One more benefit is calling sequence, when you call an instance method, code generated will push instance of this onto stack as first parameter and rest of the parameters for the method will be pushed onto the stack. So every instance method call requires one more additional stack push for this in along with other method parameters.

If you convert your method to static, static method calls do not require this so one less push operation for CPU. It doesn't seem big benefit for single call.

But if your method will be used very frequently and if you have couple of methods that do not require this then it can save significant CPU time, especially in graphics and scientific calculations.

This is the reason Resharper is suggesting you to change method to static when method does not reference anything that is part of this.

Here is the sample,

    public int Add(int a, int b) {
        return a + b;
    }

    public static int StaticAdd(int a, int b) {
        return a + b;
    }

    public void InstanceAdd() {
        Console.WriteLine(this.Add(3,3));
    }

    public void InstanceAddStatic()
    {
        Console.WriteLine(StaticAdd(3, 3));
    }

This is il generated for calling an instance method in "InstanceAdd"

.method public hidebysig 
    instance void InstanceAdd () cil managed 
{
    // Method begins at RVA 0x2095
    // Code size 16 (0x10)
    .maxstack 8

    IL_0000: nop
    IL_0001: ldarg.0
    IL_0002: ldc.i4.3
    IL_0003: ldc.i4.3
    IL_0004: call instance int32 Temp.MathTest::Add(int32, int32)
    IL_0009: call void [System.Console]System.Console::WriteLine(int32)
    IL_000e: nop
    IL_000f: ret
} // end of method MathTest::InstanceAdd

and this is the il generated for instance method in "StaticAdd"

.method public hidebysig 
    instance void InstanceAddStatic () cil managed 
{
    // Method begins at RVA 0x20a6
    // Code size 15 (0xf)
    .maxstack 8

    IL_0000: nop
    IL_0001: ldc.i4.3
    IL_0002: ldc.i4.3
    IL_0003: call int32 Temp.MathTest::StaticAdd(int32, int32)
    IL_0008: call void [System.Console]System.Console::WriteLine(int32)
    IL_000d: nop
    IL_000e: ret
} // end of method MathTest::InstanceAddStatic

If you look at "StaticAdd", there is no ldarg.0, which is this. For every method call, there will always be ldarg.0 as first instruction and then rest of the parameters will follow.

like image 135
Akash Kava Avatar answered Dec 30 '22 14:12

Akash Kava