Eln*_*naz 3 c# static-methods private-members
我有一个公共课叫MyClass.cs.它有3种方法:
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>
}
}
Run Code Online (Sandbox Code Playgroud)
我使用ReSharper作为重构工具.它建议static用于MyPrivateMethod.
private static IEnumerable<AnotherDto> MyPrivateMethod(IEnumerable<SomeDto>)
Run Code Online (Sandbox Code Playgroud)
但是这个关键字的用法是什么?由于该方法是私有的,因此不会在其他想要使用MyClass实例的类中使用.
我测试并发现,当我使用static关键字时MyPrivateMethod,我不能调用非私有静态的类的任何其他方法.但我还不知道用法是什么?例如,存储或时间优化是否有任何好处?
根据MSDN
不访问实例数据或调用实例方法的成员可以标记为static(在Visual Basic中为Shared).将方法标记为静态后,编译器将向这些成员发出非虚拟调用站点.发出非虚拟调用站点将阻止在运行时检查每个调用,以确保当前对象指针为非null.这可以为性能敏感的代码实现可测量的性能增益.在某些情况下,无法访问当前对象实例表示正确性问题.
https://msdn.microsoft.com/en-us/library/ms245046.aspx
另一个好处是调用序列,当您调用实例方法时,生成的代码将把实例this作为第一个参数推送到堆栈,并且该方法的其余参数将被推送到堆栈.因此,每个实例方法调用都需要一个额外的堆栈推送this以及其他方法参数.
如果将方法转换为静态方法,则静态方法调用不需要this对CPU进行少量推送操作.单次通话似乎没什么大不了的.
但是,如果您的方法将被频繁使用,并且如果您有几种不需要的方法,this那么它可以节省大量的CPU时间,尤其是在图形和科学计算中.
这是Resharper建议您在方法不引用任何属性时将方法更改为静态的原因this.
这是样本,
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));
}
Run Code Online (Sandbox Code Playgroud)
这是为了在"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
Run Code Online (Sandbox Code Playgroud)
这是在"StaticAdd"中为例如方法生成的il
.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
Run Code Online (Sandbox Code Playgroud)
如果你看一下"StaticAdd",没有ldarg.0,这是this.对于每个方法调用,总会有ldarg.0第一条指令,然后其余的参数将会跟随.