happyhippy

这个世界的问题在于聪明人充满疑惑,而傻子们坚信不疑。--罗素

1. 禁止在一个类的静态构造函数中访问另一个类中的静态成员。
   猜下下面这段程序的输出结果:

using System;
using System.Threading;

namespace TypeConstructorLock
{
    
class Class1
    
{
        [STAThread]
        
public static void Main(string[] args)
        
{
            Thread threadA 
= new Thread(new ThreadStart(TouchStatic1));
            threadA.Name 
= "Thread A";
      
            Thread threadB 
= new Thread(new ThreadStart(TouchStatic2));
            threadB.Name 
= "Thread B";
 
            threadA.Start();
            threadB.Start();
            threadA.Join();
            threadB.Join();
        }

 
        
static void TouchStatic1() string s = Static1.Message; }
        
static void TouchStatic2() string s = Static2.Message; }
    }


    
class Static1
    
{
        
static Static1()
        
{
            Console.WriteLine(
"Begin Static1 .cctor on thread {0}"
                Thread.CurrentThread.Name);
            Thread.Sleep(
5000);
            Console.WriteLine(
"//Static1 has a message from Static2: {0}"
                Static2.Message);      
            message 
= "Hello From Static1";
            Console.WriteLine(
"Exit Static1 .cctor on thread {0}"
                Thread.CurrentThread.Name);
        }

 
        
static public string Message get return message; } }
        
static string message = "blank";
    }

 
    
class Static2
    
{
        
static Static2()
        
{
            Console.WriteLine(
"Begin Static2 .cctor on thread {0}"
                Thread.CurrentThread.Name);
            Thread.Sleep(
5000);
            Console.WriteLine(
"//Static2 has a message from Static1: {0}"
                Static1.Message);         
            message 
= "Hello From Static2";
            Console.WriteLine(
"Exit Static2 .cctor on thread {0}"
                Thread.CurrentThread.Name);
        }

 
        
static public string Message get return message; } }
        
static string message = "blank";    
    }

}

   执行结果:

E:CSC>staticlock.exe
Begin Static1 .cctor on thread Thread A
Begin Static2 .cctor on thread Thread B
//Static2 has a message from Static1: blank
Exit Static2 .cctor on thread Thread B
//Static1 has a message from Static2: Hello From Static2
Exit Static1 .cctor on thread Thread A



    留意上面的“//static2 has a message from static1:black”,里面取得的字符串值是“blank”,而不是“Hello From Static1”,我们不能确定两个静态构造函数中的两条message赋值语句谁已经执行或没有执行! 这里要记住一条规则:禁止在一个类的静态构造函数中访问另一个类中的静态成员(Avoid touching the static members of another type from within a type constructor)。虽然我们很少情况下会写出上面这种代码,但一旦写出来了,这种错误将很难调试,我们要牢记这样准则。

 

2. 如果静态构造函数中有异常(用E描述)抛出,则CLR会对E进行包装,重新抛出一个System.TypeInitializationException异常,而把E作为该异常的InnerException。在进行程序设计时,我们一定要保证在类的静态构造函数不能有异常抛出!


3. C#中不支持子类继承父类的静态成员,但却可以通过子类类名来访问父类的静态成员!
   反射静态成员的示例:

using System;
using System.Reflection;
namespace Reflection
{
    
class Class1
    
{
        [STAThread]
        
static void Main(string[] args)
        
{           
            Type type;              
            
object result;
            PropertyInfo[] properties;
            
            
object instance = null;
            
object[] index = null;
            
            type 
= typeof(Static1);
            
            properties 
= type.GetProperties(BindingFlags.Static | BindingFlags.Public);            
            result 
= properties[0].GetValue(instance, index);//注意:访问内的静态成员,这里传入的是null
            Console.WriteLine(result.ToString());
            
            type 
= typeof(Static2);
            
            properties 
= type.GetProperties(BindingFlags.Static | BindingFlags.Public |
                 BindingFlags.FlattenHierarchy);
//如果不运用FlattenHierarchy,则返回空数组。
        /*FlattenHierarchy:指定应返回层次结构上的公共静态成员和受保护的静态成员。
         * 不返回继承类中的私有静态成员。静态成员包括字段、方法、事件和属性。不返回嵌套类型。
         *
         * FlattenHierarchy告诉CLR将基类Static1的静态属性也算在内!
         * C#中不支持子类继承父类的静态成员,但却可以通过子类类名来访问父类的静态成员!
         * e.g.:我们可以通过访问Static2.Message来访问Static1.Message
         *  
*/

            result 
= properties[0].GetValue(instance, index);
            Console.WriteLine(result.ToString());

        Console.WriteLine(Static2.Message);
        }

    }

            
    
class Static1
    
{
        
static public string Message get return message; } }
        
static string message = "Hello World 1";
    }

            
    
class Static2 : Static1{}
}

   执行结果:

E:CSC>refstatic.exe
Hello World 
1
Hello World 
1 

 

 

参考:http://msdn.microsoft.com/msdnmag/issues/05/01/StaticsinNET/default.aspx


posted on 2007-04-05 18:58  Silent Void  阅读(1052)  评论(0编辑  收藏  举报