C#vs C++中的新操作符

OMG*_*chy 7 c# c++ new-operator

来自C++,我对new在C#中使用关键字感到困惑.

我知道它不像C++一样工作new,因为你不必手动控制对象的生命周期,因为C#有垃圾收集.

但是,当阅读其他人的C#代码时,我会注意到代码片段1中的语句.如果new在代码片段2 中完全避免使用它会不会更容易?

片段1

Foo fooInstance = new Foo();
Run Code Online (Sandbox Code Playgroud)

片段2

Foo fooInstance;
Run Code Online (Sandbox Code Playgroud)

我的问题是,代码段1和代码段2之间有什么区别,为什么我更喜欢一个呢?

nvo*_*igt 9

假设Foo是类的引用类型,第二个代码片段基本上只分配一个指针.等效的C++代码

Foo* fooInstance;
Run Code Online (Sandbox Code Playgroud)

您的第一和第二个片段根本不相同.

  • 谢谢,尽管我认为由于垃圾回收而不是原始指针,它更像是`std :: shared_ptr <Foo> fooInstance;`? (2认同)
  • 嗯,两者都不完全适合这个法案.这是一个垃圾收集参考.C++没有类似的东西.我想只要没有调用'new`我们都是对的,一旦有了,我们都有点错了:) (2认同)

Jep*_*sen 4

我们必须区分三种情况:

  1. 局部变量
  2. 结构内的(非静态)字段
  3. 类内的字段

对于局部变量,即在方法内部(或构造函数内部,或属性/索引器/事件访问器)声明的变量,两者并不等效:

class C
{
  void M()
  {
    Foo fooInstance = new Foo();
    // the variable is "definitely assigned" and can be read (copied, passed etc)
    // consider using the 'var' keyword above!
  }
}

class C
{
  void M()
  {
    Foo fooInstance;
    // the variable is not "definitely assigned", you cannot acquire its value
    // it needs to be assigned later (or can be used as 'out' parameter)
  }
}
Run Code Online (Sandbox Code Playgroud)

例如 a 内的字段(非静态字段)struct,只允许使用“片段”之一:

struct S
{
  Foo fooInstance = new Foo(); // compile-time error! cannot initialize here
}

struct S
{
  Foo fooInstance; // OK, access level is 'private' when nothing is specified
}
Run Code Online (Sandbox Code Playgroud)

对于类内部的字段(以及static结构体的字段),情况取决于Foo其本身是引用类型 ( class) 还是值类型 (structenum)。default(Foo)引用类型的默认值为null,即不引用任何内容的引用。默认值default(Foo)或值类型是所有字段都有默认值的类型的“实例”。对于值类型(结构体和枚举),new Foo()(无参数) 和default(Foo)是同一件事。所以:

class C
{
  Foo fooInstance = new Foo(); // OK, private
}

class C
{
  Foo fooInstance; // OK, private
  // equivalent to 'Foo fooInstance = null;' if 'Foo' is a reference type (class, interface, delegate, array)
  // equivalent to 'Foo fooInstance = new Foo();' is 'Foo' is a value type (struct, enum)
}
Run Code Online (Sandbox Code Playgroud)

应该注意的是,如果Foo是引用类型,则new Foo()仅当该类型实际上具有接受 0 个参数的构造函数并且该构造函数可访问时才允许使用该表达式。

在(1)中,我们忽略了一个愚蠢的情况,即Foo是一个没有实例字段的结构。