2011-08-24 125 views
2

如果某個對象是隻讀或常量,是否可以將該對象轉換爲可寫? 與C++ const_cast類似。C#可以強制轉換爲const嗎?

+2

你是在談論對象本身,還是對對象的引用? –

+3

如果你需要寫信給它,爲什麼不直接刪除整個const的想法呢? – Lloyd

回答

12

這在C#中是不可能的,就像在C++中不可能的那樣。在C++中,如果對象是真正的常量,你不能const_cast常量性遠和寫入而不調用未定義的行爲:

struct foo { const int x; }; 

foo a; 
int& b = const_cast<int&>(a.x); 
b = 17; // invokes undefined behaviour 

在C#中readonly場僅表示該字段本身不能被重新分配。這與C++中的T *constT&類似。您可以通過其成員隨意更改引用的對象。

class Foo { public int x; } 
class Bar { public readonly Foo y = new Foo(); } 

Bar a = new Bar(); 
a.y.x = 3; // valid 
a.y = new Foo(); // invalid 

那麼,我沒有講完整個事實。你可以欺騙,並通過反射改變readonly領域:

typeof(string).GetField("Empty").SetValue(null, "bar"); 
// this effectively makes string.Empty equal to "bar", with disastrous consequences 
// It requires full trust though. 
// Obviously, it's evil. 

如果是const場然而,即使沒有這一招會奏效。

const字段硬編碼在使用它們的組件,而不是保持引用原裝配:

// Assembly A.dll 
public class Foo { public static const int X = 42; } 

// Assembly B.dll 
int y = Foo.X; 
// this is the equivalent to: 
int y = 42; 

這意味着,如果你重新編譯A.DLL和Foo.X值更改爲23, B.dll將仍然使用42,直到它被重新編譯。

所有這一切說,如果你想有一個領域,你想改變,只是不要使它readonly。如果你希望它是由類可變的,但是從外面一成不變的,將其變爲私有,並添加一個只讀屬性(注意:這是不一樣的一個readonly場):

class Foo 
{ 
    private int bar; 
    public int Bar 
    { 
     get { return bar; } 
    } 
} 

This is not really guaranteed,但它適用於Microsoft實現。如果你想知道爲什麼這個黑客可以運行,你可以閱讀Eric Lippert's explanation。請務必閱讀關於readonly on value types的回答。不用說,不要在家裏做這個

+0

「與C++不同」不是這樣。只是C#引用的行爲更像指針,而'readonly'更像'Bar * const'而不是'const Bar *'。 – ybungalobill

+5

實際上在C++中拋出constness不會調用未定義的行爲。修改一個const對象,例如通過一個非const引用或通過拋出constness創建的指針來調用未定義的行爲。但只要你不改變const對象,就沒有UB。所以在你的例子中,拋棄是完全正常的,雖然不必要(cou可以在任何一天將const int賦給int)。如果你嘗試const_cast (a.x)= 5; - 那將是UB。 – AndrzejJ

+0

感謝所有的評論。我希望我修復所有不那麼正確的細節:) –

1

您將無法修改const本身的值。你所能做的就是拍攝一張副本並更改該副本。除非我誤解了這個問題......?

記住,在C#const是相當有限的關鍵詞無論如何,你只能申報某些事情const只有在編譯時:

http://msdn.microsoft.com/en-us/library/e6w8fe1b(v=VS.100).aspx

不知道爲什麼你會想變異一個常數。

1

否參考或值將只能讀取。

但是,您可以修改引用的屬性,或者您可以僅創建一個值的副本。

0

對象不是隻讀或常量,只有變量是。這意味着您只能爲這樣一個變量賦值(在const的情況下)或者僅在構建所有者對象之前(在readonly的情況下)。

儘管分配給readonly變量的對象仍然可以更改,除非它不可變(如string)。

相關問題