我是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数组[重复] - pythonThis 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…