C#中用户自定义类的默认值是什么?

88

我看到一些代码会返回默认值,所以我想知道对于用户定义的类,编译器会如何定义它的默认值?


3
澄清一下:所有类(包括您创建的类)将默认为“null”。数字值类型将默认为零,结构体是实现定义的(值在构造函数中设置)。 - Isak Savo
4
实际上,结构体具有一个隐式的默认构造函数,无法被重载,该构造函数会将结构体使用的内存清零,因此默认值仍由编译器定义,而不是实现定义。 - Matthew Scharley
1
重要区别:_类成员_会被初始化为它们的默认值。未初始化的本地函数变量只会导致编译器错误 ;) - Nyerguds
10个回答

100

与其他人的回答一样,它将是null,但我还应该补充一点,您可以使用default获取任何类型的默认值。

default(MyClass) // null
default(int) // 0

在处理泛型时,这个工具非常有用;如果您的返回类型是T,而且您不想假设它可为空,那么您可能希望返回default(T)


4
在 http://msdn.microsoft.com/en-us/library/xwth0h0d%28VS.80%29.aspx 上有关于默认关键字的详细解释。 - Joe Daley

21

class的默认值为null


19
注意:一个 DefaultValueAttribute 不会自动使用属性值初始化成员。您必须在代码中设置初始值。
您可以使用 DefaultValueAttribute 来装饰您的属性。
private bool myVal = false;

[DefaultValue(false)]
public bool MyProperty
{
    get
    {
       return myVal;
    }
    set
    {
       myVal = value;
    }
 }

我知道这并没有回答你的问题,只是想添加相关信息。

如需更多信息,请参见http://msdn.microsoft.com/en-us/library/system.componentmodel.defaultvalueattribute.aspx


4
如页面所述,DefaultValue 只是 VS 可视化设计师使用的一种东西。它与实际初始化完全无关,仅仅是如何初始化的“提示”。 - Nyerguds

10

我建议将这个“default”类实例作为字段而不是属性,就像 System.String.Empty 看起来的那样:

public class Person 
{
    public string Name { get; set; }
    public string Address { get; set; }

    public static readonly Person Default = new Person() 
    {
        Name = "Some Name",
        Address = "Some Address"
    };
}

...

public static void Main(string[] args)
{
    string address = String.Empty;

    Person person = Person.Default;

    //the rest of your code
}

10

类的默认值为null。对于结构体,其默认值与实例化结构体的默认无参构造函数相同(不能被覆盖)。递归地应用相同规则到类或结构体内包含的所有字段中。


8
如果你在想为什么没有一种语言特性允许你定义一个非空默认值的类,那么请记住类是“引用类型”。引用类型是指分配内存的引用,或者换句话说,除了null之外的任何东西都是该对象的构造实例,需要分配内存。因此,现在考虑如何将“default”关键字集成到.NET中,使其适用于类,可以考虑两种实现方式:
1. 您可以定义一个静态实例并标记为默认值。也许“default”变成像访问修饰符(例如public default readonly等)。这可能有效,但它真的是一个有价值的语言特性吗?至少这样,“default”将指向相同的静态内存实例。
2. 如果每次在类上使用默认关键字时都调用默认构造函数会怎样?这将是可怕的,因为如果您没有重写Equals以不比较引用,则两个默认值可能不相等,并且由于构造函数的内存管理和内存分配性能损失以及副作用而可怕。
所以总结一下,我认为这不是我们真正想要的语言特性。并且default(MyClass)始终== null。

很好的解释。我有点儿的印象,default 只是当 IDE 建议将 null 替换为通用的 <T> 时,它只是一个替代品。 - Govind Parmar

5
如果它是引用类型,那么默认值将是null;如果它是值类型,则取决于具体情况。

4
Assert.IsTrue(default(MyClass) == null);

3
这个 assert 的目的是什么? - Alex Gordon

2

对于引用类型或可空值类型,其默认值将为null

Person person = default; // = null
IEnumerable<Person> people = default; // = null
int? value = default; // = null

对于值类型而言,这取决于它是哪种值类型:
int value = default; // = 0
DateTime dateTime = default; // = 1/1/0001 12:00:00 AM
Guid id = default; // = 00000000-0000-0000-0000-000000000000

0

希望能够节省其他人的时间。

当今明显的选项(我仍然需要谷歌一下,因为首先遇到了这个主题)是编写一个扩展程序,帮助您初始化一个类,而不管它自己的复杂性(比如构造函数getters/setters防止简单的默认值直接赋值)。

稍微修改之前的答案:

public class Person 
{
    public string Name { get; set; }
    public string Address { get; set; }

    public static readonly Person Default = new Person() 
    {
        Name = "Some Name",
        Address = "Some Address"
    };
}

=>

public class Person 
{
    public string Name { get; set; }
    public string Address { get; set; }
}
public static class PersonExtentions
{
    public static Person withDefaults(this Person obj) {
      obj.Name = "John Doe";
      return obj;
    }
}

然后

Person x = new Person.withDefaults();

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