我不明白为什么我们需要'new'关键字 - c#

我是C#的新手,来自C ++背景。在C ++中,您可以执行以下操作:

class MyClass{
....
};
int main()
{
   MyClass object; // this will create object in memory
   MyClass* object = new MyClass(); // this does same thing
}

而在C#中:

class Program
{
    static void Main(string[] args)
    {
        Car x;
        x.i = 2;
        x.j = 3;
        Console.WriteLine(x.i);
        Console.ReadLine();

    }
}
class Car
{
    public int i;
    public int j;


}

你做不到我不知道为什么Car x不会做它的工作。

参考方案

在这个问题本身和几个答案中都存在很多误解。

让我开始研究问题的前提。问题是“为什么在C#中需要new关键字?”这个问题的动机是C ++的这个片段:

 MyClass object; // this will create object in memory
 MyClass* object = new MyClass(); // this does same thing

我有两个理由批评这个问题。

首先,它们在C ++中不会做同样的事情,因此问题基于对C ++语言的错误理解。了解C ++中这两件事之间的区别非常重要,因此,如果您不太清楚地了解两者之间的区别,请找一位可以指导您如何了解区别以及何时使用它们的导师。

其次,这个问题以(错误地)为前提,即这两种语法在C ++中做相同的事情,然后奇怪地问:“为什么在C#中需要new?”给定这个正确的问题,当然又是错误的,前提是“为什么我们在C ++中需要new”?如果这两种语法在做相同的事情,而实际上却不在,那么为什么要首先使用两种语法呢?

因此,这个问题都基于错误的前提,关于C#的问题实际上并不是从C ++的设计(被误解)中得出的。

真是一团糟。让我们抛出这个问题,提出一些更好的问题。让我们问关于C#或C#的问题,而不是在C ++的设计决策范围内。

new X运算符在C#(X是类或结构类型)中做什么? (在此讨论中,让我们忽略委托和数组。)

新的运算符:

导致分配给定类型的新实例;新实例的所有字段均初始化为默认值。
导致执行给定类型的构造函数。
如果对象是引用类型,则生成对已分配对象的引用;如果对象是值类型,则生成对值本身的引用。

好的,我已经可以听到C#程序员的反对,所以让我们消除它们。

异议:如果您是值类型,则不会分配新的存储。好吧,C#规范与您不同意。当你说

S s = new S(123);

对于某些结构类型S,规范说在短期池上分配了新的临时存储,并初始化为其默认值,构造函数运行时将this设置为引用临时存储,然后生成结果对象复制到s。但是,允许编译器使用复制删除优化,前提是它可以证明不可能在安全程序中观察到该优化。 (锻炼:找出在什么情况下不能执行复制省略;给出一个程序示例,该程序如果使用或不使用省略都会有不同的行为。)

异议:可以使用default(S)产生值类型的有效实例;没有调用构造函数,我听你说。没错我并不是说new是创建值类型实例的唯一方法。

实际上,对于值类型,new S()default(S)是同一件事。

异议:是否真的在new S()之类的情况下执行了构造函数,如果C#6的源代码中没有该构造函数,我听到您说过。这是“如果一棵树掉在森林里,没人听见,它会发出声音吗?”题。调用不执行任何操作的构造函数与完全不执行调用之间有区别吗?这不是一个有趣的问题。编译器可以随意取消其不知道执行的任何调用。

假设我们有一个值类型的变量。我们必须使用new产生的实例来初始化变量吗?

不会。自动初始化的变量(例如字段和数组元素)将被初始化为默认值,即所有字段本身都是其默认值的结构的值。

显然,形式参数将使用参数进行初始化。

在读取字段之前,必须为值类型的局部变量明确赋值,但不必是new表达式。

如此有效地,除非它们是本地变量,否则将使用等价于default(S)的值类型的变量自动对其进行初始化?

是。

为什么不对当地人做同样的事情?

未初始化的本地语言的使用与错误代码紧密相关。 C#语言不允许这样做,因为这样做会发现错误。

假设我们有一个引用类型的变量。我们必须使用S产生的实例来初始化new吗?

不会。自动初始化变量将使用null进行初始化。可以使用任何引用(包括null)来初始化本地,并且必须在读取之前明确地分配本地。

如此有效,引用类型的变量会自动用null初始化,除非它们是本地变量?

是。

为什么不对当地人做同样的事情?

相同的原因。一个可能的错误。

为什么不通过自动调用默认构造函数来自动初始化引用类型的变量?也就是说,为什么不使R r;R r = new R();相同?

好吧,首先,许多类型没有默认构造函数,或者根本没有任何可访问的构造函数。第二,对于未初始化的本地或字段,有一个规则,对于形式化,有另一个规则,而对于数组元素有另一个规则,这似乎很奇怪。第三,现有规则非常简单:必须将变量初始化为值;该值可以是您喜欢的任何值;为什么要保证需要一个新实例呢?如果这是奇怪的

R r;
if (x) r = M(); else r = N();

使构造函数运行以初始化r

除了new运算符的语义之外,为什么在语法上必须有这样的运算符?

不是。有许多语法可以替代的语法。最明显的是完全消除new。如果我们有一个带有构造函数C的类C(int),那么我们可以简单地说C(123)而不是new C(123)。或者我们可以使用类似C.construct(123)的语法或类似的东西。没有new运算符,有许多方法可以做到这一点。

那为什么呢?

首先,C#旨在使C ++,Java,JavaScript和其他使用new表示正在为对象初始化新存储的语言的用户立即熟悉。

其次,非常需要正确级别的语法冗余。对象创建很特殊;我们希望在它自己的运算符发生时发出通知。

错误CS0027:关键字'this'在当前上下文中不可用 - c#

我有以下构造函数的初始化:public partial class WizardPage1 : WizardPage { public WizardPage1() : base(0, getLocalizedString(this.GetType(), "PageTitle")) { } } 哪里public static string …

将字符串分配给numpy.zeros数组[重复] - python

This question already has answers here: Weird behaviour initializing a numpy array of string data                                                                    (4个答案)         …

'ConfigurationBuilder'不包含'AddJsonFile'的定义 - c#

我有以下错误:Program.cs(15,72):错误CS1061:“ ConfigurationBuilder”不包含“ AddJsonFile”的定义,并且找不到包含“ ConfigurationBuilder”类型的第一个参数的可访问扩展方法“ AddJsonFile”(您是否缺少使用指令或汇编该项目是一个使用Azure Search SDK的dotn…

为什么使用'=='或'is'比较字符串有时会产生不同的结果? - python

我有一个Python程序,其中将两个变量设置为'public'值。在条件表达式中,我有比较var1 is var2失败,但如果将其更改为var1 == var2,它将返回True。现在,如果我打开Python解释器并进行相同的“是”比较,则此操作成功。>>> s1 = 'public' >>…

单行的'if'/'for'语句是否使用Python样式好? - python

我经常在这里看到某人的代码,看起来像是“单线”,这是一条单行语句,以传统的“if”语句或“for”循环的标准方式执行。我在Google周围搜索,无法真正找到可以执行的搜索类型?任何人都可以提出建议并最好举一些例子吗?例如,我可以一行执行此操作吗?example = "example" if "exam" in exam…