2012-08-30 23 views
9

可能重複:
Can I change a private readonly field in C# using reflection?設置只讀域(這是錯誤?)

,而只是用c#播放,實現了一個奇怪的事情。

這裏是代碼:

class Program 
{ 
    static void Main(string[] args) 
    { 
     System.Diagnostics.Debug.Write(string.Empty); 

     typeof(string) 
      .GetField("Empty", BindingFlags.Static | BindingFlags.Public) 
      .SetValue(null, "Tolgahan"); 


     Console.WriteLine(string.Empty); 

     // output : Tolgahan 
    } 
} 

爲什麼反射讓我們改變只讀域?

更新:問題是「爲什麼通過反射的設置是允許的」,而不是「如何做」,所以它不是重複的。

+4

你可以做各種與反思的東西,你不能做正常。例如,您可以從其他類獲取/設置專用字段。我幾乎肯定這不是一個錯誤;至於是否可取是另一回事。 – Servy

+3

偷報價,只讀是爲了防止「墨菲,而不是馬基雅維利」 –

+0

@Dennis:另一個問題只是詢問是否有可能,這個人說,它是可能的,但問爲什麼(因此比IMO更有價值另一個)。 –

回答

14

以同樣的方式,化學定律說沒有反應可以導致一個元素的原子變成另一個元素的原子,但是物理定律說它總是發生。化學是物理學的一個有限子集,以便將問題簡化爲更加可解的方式。

反射是物理在這種情況下,正常編程是化學。它以更簡單的思維模式運作。反思可以讓你規避這套簡單的規則,讓你接觸新的流程,同時也帶來新的危險。

+2

多麼奇怪的比喻。不,它不是一個bug就足夠了,還是那太化學了? – Jodrell

+3

試着在Bryan Cranston的聲音中讀到它,它突然開始有意義。 –

+0

@ssg更有意義比亞倫保羅,至少:-) – corsiKa

0

它可能是因爲.Net中的反射是以這種方式實現的。我只能猜測這個動機,但它是一個功能強大(但速度很慢)的工具,可以提供很大的靈活性和潛在的誤用。

這不是唯一可以實現這種改變的方式,但這樣的討論不像任何進一步的主觀推測那樣是主題和不合適的。

3

因爲readonly,就像private,防止墨菲,而不是馬基雅維利*。

我們使用readonlyprivate和其他任何限制我們可以做的,主要是因爲我們希望有更多的限制不正確的,不一致的,或只是普通的愚蠢的事情,比我們有益和富有成效的事情。

但它仍然只是一個和零。如果某些內存設置爲數字「42」,並且我們通過只讀字段訪問它,則在創建對象時它不是隻讀的。除了編譯器發現「嘿,首先你說你不想改變它,現在你試圖改變它,給出了什麼?這兩個決定中的一個必然是錯誤的,除此之外沒有什麼可以阻止它被改變。

現在,沒有承諾反射能夠改變它,但沒有承諾它不會。目前,思考的方式和只讀方式的工作方式意味着你可以改變它。至少,它會花費大量的工作(可能會影響我們的用戶以及需要實施這項工作的團隊的成本)來阻止那些想要去做這件事的人,因爲他們認爲他們有一個很好的理由。

注意與反思的權限做站馬基雅維利,

*嚴格,墨菲在談論正是我們應該如何設計的東西阻止人們意外地做一些災難性的 - readonly就是一個很好的例子,插頭,可以」實際上被困在一個更好的方面 - 馬基雅維利正在教學而不是練習這些技巧。儘管它儘可能簡明扼要地說明了這一點。

+0

+1我真的很喜歡這個比喻。 –

+0

@ p.s.w.g Murphy和Machiavelli?我不能要求信用。我知道最早的可比較用法(關於C++中的'private')是由Bjarne Stroustrup提供的,儘管我不知道他是否是第一個。 –