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";
}
}
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
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{}
}
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
Hello World 1
Hello World 1
参考:http://msdn.microsoft.com/msdnmag/issues/05/01/StaticsinNET/default.aspx