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?
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.