none
类型构造器问题 RRS feed

  • 问题

  •   public struct Some
        {
            static Some()//类型构造器
            {
                Console.WriteLine("这句话不会显示!!!");
            }
            public int a;
        }

        class Program
        {
            static void Main(string[] args)
            {
                Some q=new Some();
                q.a = 123;
                Console.WriteLine(q.a);
                Console.ReadKey();
            }
        }

    为什么只打印123,不打印”这句话不会显示!!!“?

    2011年11月7日 23:24

答案

  • 结构不能声明默认构造函数(没有参数的构造函数)或析构函数。

    结构的副本由编译器自动创建和销毁,因此不需要使用默认构造函数和析构函数。实际上,编译器通过为所有字段赋予默认值(参见默认值表)来实现默认构造函数。

    http://msdn.microsoft.com/zh-cn/library/saxz13w4(VS.80).aspx
    http://feiyun0112.cnblogs.com/
2011年11月8日 0:45
版主
  • 因为结构体是值类型。值类型没有 Type Object Ptr,加上编译器为值类型生成默认构造函数时没有调用 base,所以根本不可能在实例化时找到其 Type,也就无法执行其默认静态构造。

    看下面的代码。

     

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Demo
    {
        class Foo
        {
            static Foo()
            {
                Console.WriteLine("Foo");
            }
        }
    
        struct Bar
        {
            static Bar()
            {
                Console.WriteLine("Bar");
            }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                Foo foo = new Foo();
                Bar bar = new Bar();
    
                Console.ReadKey();
            }
        }
    }
    
    

    输出 Foo。

    当执行 Test 静态方法后,Bar 才会执行静态类型构造。

     

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Demo
    {
        class Foo
        {
            static Foo()
            {
                Console.WriteLine("Foo");
            }
        }
    
        struct Bar
        {
            static Bar()
            {
                Console.WriteLine("Bar");
            }
    
            public static void Test()
            { 
            }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                Foo foo = new Foo();
                Bar bar = new Bar();
                Bar.Test();
    
                Console.ReadKey();
            }
        }
    }
    

    输出 Foo 和 Bar。

     


    Mark Zhou
    2011年11月8日 9:55
  • 只要表达式需要 Type Object 信息,且类型构造没有被执行时,它就会被执行。

    对于引用类型,然和情况下调用其景台实例方法,都需要 Type Object,引用类型有直接的 Type Object Ptr,因此,类型构造会被执行。

    对于值类型,由于它自身没有 Type Object Ptr,所以它要千方百计搞一个 Type Object Ptr 出来然后再执行方法 (因为方法定义在 Type Object 上),所以,执行了实例方法后,值类型请求了 Type Object,所以类型构造会被执行。new 一个值类型的实例时不需要 Type Object 信息,故此 new Bar() 不会执行类型构造。

    我在这里写过一个对于 C# 静态构造方法的解释,您可以搜索打开看看。http://social.msdn.microsoft.com/Forums/zh-CN/visualcshartzhchs/thread/cf143c51-7e6f-4e4e-bdd0-6f148170bec5/#8126d3f4-1742-4355-88a7-6eeb6a7d9884


    Mark Zhou
    2011年11月9日 8:51
  • 全部回复

    • 结构不能声明默认构造函数(没有参数的构造函数)或析构函数。

      结构的副本由编译器自动创建和销毁,因此不需要使用默认构造函数和析构函数。实际上,编译器通过为所有字段赋予默认值(参见默认值表)来实现默认构造函数。

      http://msdn.microsoft.com/zh-cn/library/saxz13w4(VS.80).aspx
      http://feiyun0112.cnblogs.com/
    2011年11月8日 0:45
    版主
  • 因为结构体是值类型。值类型没有 Type Object Ptr,加上编译器为值类型生成默认构造函数时没有调用 base,所以根本不可能在实例化时找到其 Type,也就无法执行其默认静态构造。

    看下面的代码。

     

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Demo
    {
        class Foo
        {
            static Foo()
            {
                Console.WriteLine("Foo");
            }
        }
    
        struct Bar
        {
            static Bar()
            {
                Console.WriteLine("Bar");
            }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                Foo foo = new Foo();
                Bar bar = new Bar();
    
                Console.ReadKey();
            }
        }
    }
    
    

    输出 Foo。

    当执行 Test 静态方法后,Bar 才会执行静态类型构造。

     

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Demo
    {
        class Foo
        {
            static Foo()
            {
                Console.WriteLine("Foo");
            }
        }
    
        struct Bar
        {
            static Bar()
            {
                Console.WriteLine("Bar");
            }
    
            public static void Test()
            { 
            }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                Foo foo = new Foo();
                Bar bar = new Bar();
                Bar.Test();
    
                Console.ReadKey();
            }
        }
    }
    

    输出 Foo 和 Bar。

     


    Mark Zhou
    2011年11月8日 9:55
  •  如果写成public void Test()
      { 
      }

    然后调用new Bar().Test();也会打印“Bar”

     

    还有种情况是把原先代码改成public static int a;(改成静态的)

    然后调用Some.a= 3;也会打印”这句话不会显示!!!“

    能进一步解释下在什么情况下会调用到静态构造方法吗?

    2011年11月9日 5:25
  • 只要表达式需要 Type Object 信息,且类型构造没有被执行时,它就会被执行。

    对于引用类型,然和情况下调用其景台实例方法,都需要 Type Object,引用类型有直接的 Type Object Ptr,因此,类型构造会被执行。

    对于值类型,由于它自身没有 Type Object Ptr,所以它要千方百计搞一个 Type Object Ptr 出来然后再执行方法 (因为方法定义在 Type Object 上),所以,执行了实例方法后,值类型请求了 Type Object,所以类型构造会被执行。new 一个值类型的实例时不需要 Type Object 信息,故此 new Bar() 不会执行类型构造。

    我在这里写过一个对于 C# 静态构造方法的解释,您可以搜索打开看看。http://social.msdn.microsoft.com/Forums/zh-CN/visualcshartzhchs/thread/cf143c51-7e6f-4e4e-bdd0-6f148170bec5/#8126d3f4-1742-4355-88a7-6eeb6a7d9884


    Mark Zhou
    2011年11月9日 8:51