C#100问--为什么值类型不允许定义无参构造函数?

直接回答:
为了防止开发人员对这种构造器在什么时候调用产生迷惑,导致发生影响程序性能的问题,所以干脆禁止。

详细解答:
首先CLR是允许这种行为的,只是C#编译器不允许。
当程序new一个无参的值类型时,会分配一片内存(该片内存是已经分配过的),并将这片内存的脏数据(之前存储了一些其他数据)清理掉,即zeroed,这个工作是CLR调用IL形式的initobj指令完成的。当程序new一个无参的值类型时,new操作符就被编译成initobj指令。

考虑到有些情况会使用无参构造函数,而有些情况不能使用,容易造成困惑,破坏了一致性,所以干脆禁止。比如以下这个例子:

Struct[] foo = new Struct[1000];

对于上面这个语句,CLR可以通过分配内存并zeroed化内存的方式高效完成。但如果定义了无参构造函数的话,也就意味着要执行1000次无参构造函数,极其低效。


延申问题:在struct中定义一个值类型并赋值,则会发生什么?
会编译报错:结构中不能有实例字段初始值设定项。
原因就是C#不允许为值类型定义无参构造函数,所以不会自动执行内联初始化,所以不能在值类型中内联实例字段的初始化,他们总是被初始化为0或null。

struct SomeValType
{
    // 不能在值类型中内联实例字段的初始化
    private int m_x = 5;
}

延申知识点:
值类型若要显示定义有参构造函数,则必须对所有字段显示赋值

struct SomeValType
{
    private int m_x;
    private int m_y;
    
    public SomeValType(int x, int y)
    {
        m_x = x;
        m_y = y;
    }
}

或者用这种方式

struct SomeValType
{
    private int m_x;
    private int m_y;
    
    public SomeValType(int x, int y)
    {
        // 会将所有字段全部赋值为0
        this = new SomeValType();
        // 用x覆盖m_x的0
        m_x = x;   
    }
}

替代方案中用到的this在值类型中,this可赋值,因为它是一个实例。
而引用类型中,this只读不可赋值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值