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

浙公網安備 33010602011771號