c#中这两个方法调用的区别是什么?

c#中这两个方法调用的区别是什么?,c#,class,methods,console-application,C#,Class,Methods,Console Application,例如,我有一个类,其中有一个void方法 这是我的班级: class MyClassTest { public void Print() { Console.WriteLine("Hello"); } } 我不熟悉类,有点困惑,这两个方法调用之间有区别吗 这是我的主要方法 static void Main(string[] args) { //first call MyClassTest ms = new MyClassTest();

例如,我有一个类,其中有一个
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();
}

在下面的例子中,当您希望保留对构造对象的引用并在以后使用它执行一些进一步的操作时,您将需要这样做

MyClassTest ms = new MyClassTest();
ms.Print();
MyClassTest ms = new MyClassTest();
ms.Print();
然而,在下面的例子中,只有当您不再关心构造后的构造对象,而只对调用方法
Print
感兴趣时,才需要这样做

new MyClassTest().Print();
这两种场景之间的微妙区别在于
被引用的对象执行进一步的操作,它很可能在不再被引用的对象之后被销毁,即上面作为GC(垃圾收集器)的第二个示例将发现它没有引用,因此决定将其删除。

在下面的情况下,当您希望保留对构造对象的引用并稍后对其执行一些进一步的操作时,您将需要执行此操作

MyClassTest ms = new MyClassTest();
ms.Print();
MyClassTest ms = new MyClassTest();
ms.Print();
然而,在下面的例子中,只有当您不再关心构造后的构造对象,而只对调用方法
Print
感兴趣时,才需要这样做

new MyClassTest().Print();
这两种场景之间的微妙区别在于
被引用的对象执行进一步的操作,它很可能在不再被引用的对象之后被销毁,即上面作为GC(垃圾收集器)的第二个示例您的两个调用在c#中执行相同的语义操作:区别在于,在第一个调用中,您创建了
ms
变量,这表明读者希望在代码中再次使用它:事实上,您正在调用
ms.Print()
之后

您的第二个调用没有声明任何变量,这意味着您的意图就是在代码中只对全新的
MyClassTest
实例调用一次
Print
方法,并且您不关心刚刚创建的实例


旁注:在发布模式下编译时,C#编译器将压缩并减少变量使用,因此您的两个调用将编译相同的代码,它们将与您的第二个调用类似。

您的两个调用在C#中执行相同的语义操作:区别在于,在第一个调用中,您创建了
ms
变量,这向读者表明,您的意图是在代码中再次使用它:事实上,您正在调用
ms.Print()
after

您的第二个调用没有声明任何变量,这意味着您的意图就是在代码中只对全新的
MyClassTest
实例调用一次
Print
方法,并且您不关心刚刚创建的实例


旁注:在发布模式下编译时,C#编译器将压缩并减少变量使用,因此您的两个调用将编译相同的代码,它们将与您的第二个调用类似。

实际上没有区别。当需要在程序中进一步参考
MyTestClass
时,使用第一种情况。您使用第二种情况作为“发射并忘记”。如果您计划大量使用第二种情况,建议将
Print
方法设置为
static

IL代码没有显示任何差异,除了将变量保持引用加载到堆栈时的WithInstance方法(
stloc.0
ldloc.0
IL指令):


实际上,没有什么区别。当需要在程序中进一步参考
MyTestClass
时,使用第一种情况。您使用第二种情况作为“发射并忘记”。如果您计划大量使用第二种情况,建议将
Print
方法设置为
static

IL代码没有显示任何差异,除了将变量保持引用加载到堆栈时的WithInstance方法(
stloc.0
ldloc.0
IL指令):


在这种特殊情况下,没有

任何时候,当您对另一个方法调用的结果调用一个方法时,
new
、属性访问等,请按照:

new MyClassTest().Print();
这类似于如果你做了:

var temp = new MyClassTest()
temp.Print();
所以在这种情况下,你们的两个例子是相同的

有一些不同的变体

一种是从数组或字段访问中访问的值类型对象。在这里,访问可能使用实际对象的地址,而不是制作副本。现在有可能发生相反的情况,不是创建隐式临时本地,而是删除显式本地,但这不是承诺。请注意,对于可变值类型,对于这些情况,带有和不带临时局部变量的代码在语义上也不相同(但对于更接近您的示例的情况,对象是不是
ref返回
ref
变量的方法调用的结果)

另一种是当它位于
屈服
-使用或
异步
方法的内部时。在这里,方法中的局部变量成为生成的对象中的字段(为
yield
实现
IEnumerable
和/或
IEnumerator
或为
async
实现
任务
),而我上面描述的“不可见”临时局部变量则不是。(编译器可以,而且将来可能会更好地去除在
yield
async
调用后不存在的一些字段,因此实际上不必是字段,但目前所有的局部变量都是字段)

因此,有几次显式局部变量只需对其进行一次操作,与直接对获取值的方法进行操作略有不同,尽管您的示例是