“default”和“new”关键字有什么区别?

11

以下是一个示例类:

public class Loan
{
}

现在,下面这两行代码有什么区别?它们之间的差异是什么?

Loan loan = default(Loan);
Loan loan = new Loan();

有偏好使用其中的一个吗?


检查loan==null怎么样? - L.B
部分内容被 https://dev59.com/JnE95IYBdhLWcg3wJKp_ 所覆盖。 - pmcoltrane
2
这两行代码的作用不同。其中一行是 null,而另一行则是创建了一个新实例。 - Magnus
4个回答

20

default用于将值清零。对于引用类型,这意味着null。对于值类型而言,这等效于使用没有参数的new。对于泛型,default非常实用。

new创建该类型的一个实例,调用构造函数。

在您的示例中,如果我执行:

Loan loan = default(Loan);

或在较新版本的C#中:

Loan loan = default;

等价于

Loan loan = null;

如果您不构造它,将会得到一个空引用异常:

loan.MakePayment(100); // Throws

你可能想要更新这个答案:自从C# 10开始,为结构体编写显式的默认构造函数是合法的,因此对于结构体来说,new和default不再是同一回事了。 - Thomas Levesque

6
更新:从C# 10开始,可以为结构体声明一个显式的默认构造函数,这使得我原来的答案是错误的。
对于没有显式默认构造函数的值类型(即结构体),default(T)和new T()在效果上是相同的:它们都返回一个未初始化的T实例。
对于具有显式默认构造函数的值类型,default(T)返回一个未初始化的实例,而new T()返回一个使用默认构造函数初始化的新实例。
对于引用类型,default(T)返回null,而new T()返回一个使用默认构造函数初始化的新实例。
在你的代码中,Loan是一个类,所以default(Loan)返回null。

原始答案 - 自 C# 10 起不再正确。

对于值类型(即结构体),default(T)new T() 实际上是相同的:它们都返回一个未初始化的 T 实例。然而,对于引用类型,default(T) 返回 null,而 new T() 返回一个使用默认构造函数初始化的新的 T 实例。

在你的代码中,Loan 是一个类,所以 default(Loan) 返回 null。


我其实不确定这是真的。如果你创建一个包含三个整数的结构体,并且有一个默认构造函数将它们设置为1、2、3,我相当确定默认值仍然会给你一个全是零的结构体,而new()会给你1、2、3。 - PreventRage
1
@PreventRage确实。这是因为过去不允许为结构体编写显式默认构造函数,但现在可以了。我会更新我的答案。 - Thomas Levesque

5

default会返回值类型的default值,对于引用类型则会返回null

如果你的Load是一个类,则第一行会返回null,而第二行会返回Loan的一个新实例。

Loan loan = default(Loan); // null if Loan is a reference type
Loan loan = new Loan(); // new instance of Loan - Not Null

如果 Loan 是一个 struct 类型(或值类型),那么上述两个方法(defaultnew)将会是相同的。

1
值类型的好注释 - Sergey Berezovskiy

1
在泛型类和方法中,一个常见问题是在不提前知道以下情况的情况下如何为参数化类型T分配默认值:
Whether T will be a reference type or a value type.

If T is a value type, whether it will be a numeric value or a struct.

给定一个参数化类型T的变量t,语句t = null仅在T是引用类型时有效,而t = 0仅适用于数值类型,但不适用于结构体。解决方案是使用default关键字,它将为引用类型返回null,对于数值型则返回0,结构体将返回每个成员初始化为零或null,具体取决于它们是值类型还是引用类型。对于可空值类型,default返回一个System.Nullable,其初始化方式与任何结构相同。

在C#中,new关键字可用作运算符、修饰符或约束。

new运算符

Used to create objects and invoke constructors.

新的修改器
Used to hide an inherited member from a base class member.

新的约束条件
Used to restrict types that might be used as arguments for a type parameter in a generic declaration.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接