const和值对象以及编译时常量

首先看一个例子:

        private static int s_n = 0;

        private static void M(int x = 9,string s = "A",DateTime     dt = default(DateTime),
            Guid guid = new Guid())
        {
            System.Console.WriteLine("x={0},s = {1},dt={2},guid={3}", x, s, dt, guid);
        }

        public static void Main()
        {
            M();
            M(8, "X");
            M(5, guid: Guid.NewGuid(), dt: DateTime.Now);
            M(s_n++, s_n++.ToString());
            M(s: (s_n++).ToString(), x: s_n++);
        }

/**在定义的方法中,如果为部分参数指定了默认值,请注意下列规则
* …
*
* 默认值必须是编译时能确定的常量值,那么,能为那些参数设置默认值呢?这些参数的类型
* 可以是c#认定的基元类型。还包括枚举类型,以及能设为null的任何引用类型。对于任何
* 值类型的一个参数,可将默认值设为值类型的一个实例,并让它的所有字段都包含零值。可以
* 用default关键字或者new关键字来表达这个意思;两种语法将生成完全一致的IL代码。在
* M方法中设置dt参数和guid参数的默认值时,分别使用的就是这两种语法。
*/
这是书中的一段话,就是这段话让人产生了疑惑。默认值必须是编译时能确定的常量。但是参数里面有 guid = new Guid(); 这明明是运行时才可以知道的,怎么能是编译时可以确定呢?
首先,我清楚Guid是一个struct值类型。现在这个new,不过是将Guid中的数据全部置为0【还是在堆栈上】,那么。。。。new 应该还是运行时吖,问题拿到群里,和众人讨论,有群友说,对于值类型,new将数据清零,这是可以预知的行为,因此可能可以在编译时确定。于是假设这个成立,我写出了const Guid g = new Guid();结果这样的语句无法通过,因为const的语义就是编译时期常量,如果new Guid()是编译时期常量,那么应该是可以通过的。这个问题矛盾了好久才发现,对于值类型,const只能修饰一些基元类型。【汗】,
同时,我写下了如下代码:

        public struct MyStruct
        {
            private int i;
            public MyStruct(int i)
            {
                this.i = i;
            }
        }

        //提示: ms的默认值必须是编译时常量。
        public void fun(string s = "hello", MyStruct ms = new MyStruct(5))
        {

        }

将其注释起来,加入:

         public void fun(string s = "hello", MyStruct ms = new MyStruct())
        {
        }

没有问题。这也验证了群友的那句话,对于值类型,new 无参构造函数的行为是可以预知的【因为编译器不允许定义无参构造函数】。

同时也发现了一个“有趣”的问题。对于c#的值类型,即使提供了一个有参数的构造函数,依旧可以使用无参构造函数【编译器此时提供的】。而这样的代码:

        public class MyClass
        {
            private int i;
            public MyClass(int i)
            {
                this.i = i;
            }
        }
        //编译出错,提示 不包含0个参数的构造函数【符合预期和c++,java中行为语义一致】
        public void fun2(string s = "world", MyClass mc = new MyClass())
        {

        }

如果将class改为struct,那么就是没有问题的。

ps: 对于struct值类型,编译器默认是不会为其产生构造函数的。对于包含在引用类型中的值类型,是不会调用其构造函数的,除非使用者显式调用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值