公司的網站出現了一個奇怪的問題,當打開一個網址的時候看到的并不是網址所應該呈現的頁面,而是一個其他的網頁,偶爾會是應該呈現的頁面,這就很奇怪了,做了斷點調試之后發現了更詭異的事情,居然傳遞的參數都獲取不到,而是直接得到了另一個值,最后發現是因為公司的一個程序員居然把參數定義成了公有的靜態變量,最后把公有靜態變量取消重新定義了變量文件解決。
在C#中,static變量表示該變量屬于類,而不是類的實例??梢哉f是該類的所有實例共享一個static變量。
asp.net的頁面就是一個類,我們訪問一個頁面。就會在服務器上實例化一個該類的實例,來響應我們的請求。“所有實例共享一個static變量” 這就意味著,所有的客戶端訪問到的asp.net頁面中static變量都是同一個變量。
由于我們每次訪問asp.net頁面都是一個全新的對象,而不是我們上一次訪問的對象。所以上次頁面訪問時我們對頁面中變量的改動都沒有保留。遇到這個問題的時候,很多初學者的直覺就是將這個變量申明為static,自己在測試的時候發現還真的保留住了頁面的狀態。竊喜之余沒有發現這又有引入了另外一個錯誤。因為你要的只是頁面能保留住狀態,而這個狀態是針對一個客戶端的(session的效果)。而得到的結果是只要一個客戶端改變了該值所有的其他客戶端都受到了影響(如同Applicatin的效果)。這種情況下,需要的極有可能就是個ViewState或者是Session。
Application與static變量
Application是通過一個集合保存所有的對象。
強類型:Application中保存的是object,對對象的保存和使用需要作cast動作。對于值類型更需要Box&UnBox。對性能的影響較大。而static變量是強類型的對象。
線程同步:Application將所有的對象放到一個集合,這樣對訪問集合中的任何對象都會鎖定這個集合。假如有Application["A"]、Application["B"]、Application["C"],有線程訪問Application["A"]其他線程不能訪問Application["B"] and Application["C"]。
而static變量,可以根據他們的作用分別放在不同的class當中。這樣可以并行訪問不同的static變量,而不存在線程安全問題。
友情提示:
1. 對static變量,做lock時??梢酝ㄟ^lock(typeof(classname))來鎖定該變量所在的類的類型,達到線程同步的目的。
2. 由于Aplication,static member是全局變量,而我們是在多線程服務器環境寫程序,對他們的使用需要注意線程安全的問題。
asp.net和C++中的static并沒有多少不同,實質上他們都是在編譯期就已存在的地址空間。換句話說,在你Build成功之后,項目的DLL文件中已經存在了這個static變量(或者類)的空間,亦即在你運行時系統載入DLL后這個變量/類的所謂實例已經存在,而且是應用程序所公用,所以你才可以直接使用,同時所有的頁面用的都是同一塊空間。
普通的類你需要new一個instance才可以使用,原因就在于應用程序中間只有聲明而沒有定義,new的時候就在堆里劃分一塊空間給他的一個實例。
一個簡單的實驗,大家就很容易的明白他們之間的區別:新建個簡單的project,添加一個類,類增加一個變量,編譯,記錄dll文件的大??;然后把變量變成static變量(當然你的class也必須成為static的了,想想這是為什么),編譯,記錄dll文件大??;比較兩個dll大小,是不是后面一個比前面大呢?
信息網址:http://www.respectj.cn/ziyuan/view20212.htm