例如,我有一些课程中有一个void
方法。
这是我的班级:
class MyClassTest
{
public void Print()
{
Console.WriteLine("Hello");
}
}
我是新手并且很困惑,这两个方法调用之间有区别吗?
这是我的主要方法
static void Main(string[] args)
{
//first call
MyClassTest ms = new MyClassTest();
ms.Print();
//second call
new MyClassTest().Print();
}
答案 0 :(得分:5)
在下面的情况中,当你想要保留对构造对象的引用并稍后用它执行一些进一步的操作时,你会想要这样做。
MyClassTest ms = new MyClassTest();
ms.Print();
然而,在下面的情况下,只有 才会在构建后不再关心构造对象但只想调用方法Print
时执行此操作。
new MyClassTest().Print();
这两种情况之间的细微差别在于: 被引用的对象执行进一步的操作,它很可能比不再引用的对象晚被销毁,即上面的第二个例子,因为GC(垃圾收集器)会发现它没有引用,因此决定去掉它
答案 1 :(得分:2)
实际上没有区别。当您需要在程序中进一步引用MyTestClass
时,可以使用第一种情况。您将第二种情况用作fire-and-forget
。如果您计划大量使用第二个案例,建议您将Print
方法设为static
。
IL代码没有区别,除了WithInstance方法,当变量保持引用加载到堆栈上时(stloc.0
和ldloc.0
IL指令):
MyClassTest ms = new MyClassTest();
ms.Print();
new MyClassTest().Print();
答案 2 :(得分:0)
你的两个调用在c#中执行相同的语义操作:不同之处在于,在第一次调用中,你创建了ms
变量,这表明你的意图是在你的代码中再次使用它:事实上,你之后正在调用ms.Print()
。
您的第二个电话,不会声明任何变量,这意味着您的意图只是在您的代码中仅在一个全新的Print
个实例上调用MyClassTest
方法,并且您没有&#39 ; t关心刚刚创建的实例。
附注:在发布模式下编译时,C#编译器会压缩并减少变量的使用,因此你的两个调用将编译相同,它们就像你的第二次调用一样。
答案 3 :(得分:0)
在这种特殊情况下,没有。
任何时候根据另一个方法调用,new
,属性访问等的结果调用方法:
new MyClassTest().Print();
它类似于你做过:
var temp = new MyClassTest()
temp.Print();
所以在这种情况下你的两个例子是相同的。
有些变体有所不同。
一种是从数组或字段访问访问的值类型对象。这里访问可能使用实际对象的地址而不是复制。现在可能发生相反的情况,而不是创建隐式临时本地而删除显式本地,但不承诺。请注意,对于可变值类型,具有和不具有临时局部的代码在这些情况下在语义上也不相同(但是对于更接近您的示例的情况,其中对象是方法调用的结果,而不是' ta ref return
到ref
变量。)
另一种情况是它位于yield
内 - 使用或async
方法。这里,方法中的locals成为生成的对象中的字段(对IEnumerable<T>
实现IEnumerator<T>
和/或yield
或Task
为async
虽然&#34;看不见&#34;我上面描述的临时本地人没有。 (编译器可以,并且将来可能会更好地删除yield
或async
次呼叫后不存在的其中一些,因此不要真的必须是田野,但暂时所有当地人都成了田地。)
因此,有些情况下,对它们进行单个操作的显式局部文件与直接对获取值的方法进行操作略有不同,尽管您的示例不是其中一个时间。