2013-06-28 114 views
2

有沒有辦法有一個變量設置爲一個對象,並有另一個變量是恆等於前一個?同義詞是否存在?

var x = new object(); 
var y = [synonym of x]; 
x = null; // then y = null as well 

我不認爲這存在。

所以我經常用數組來保存「引用」。

var x = new object[] { new object() }; 
var y = x; 
x[0] = null; // then y[0] = null as well 

但它感覺有點跛腳。

+1

你爲什麼要這麼做? – ctn

+0

你通常在C#中有引用,所以我不確定你的意思。 – Skurmedel

+0

@Skurmedel不是我的例子,數組清除了事情? – Serge

回答

3

你可以做到這一點,但你必須付出的代價是使用無證關鍵字/功能。他們從很久以前在那裏,也許他們不會改變或消失,但...

它會讓你的代碼更復雜的閱讀(如果語言本身支持的可能是有用的),但它是雙向的並且您可以圍繞原始對象移動,更改將始終反映到您的「參考」中。它不同於穆罕默德阿塔斯的答案,因爲你可以將原始對象傳遞給另一個函數更改將傳播到您的同義詞。它們有侷限性(它們不能用於類字段),但它們適用於參數和局部變量。

你需要的是一個TypedReference,它擁有一個參考到另一個變量,那麼如果你給它分配一個新的值,你會改變原來的變量。理論上這可以打開同義詞的大門,如果有一天他們會認爲這是一個很好的特徵。

讓我們看一個例子:

var text = "initial value"; 
var synonym = __makeref(text); 

現在synonym是文字的引用(請注意這是到text參考,不將其持有的價值)。要獲得從TypedReference原值使用__refvalue這樣的:

Console.WriteLine(__refvalue(synonym, string)); 

它們具有相同的價值:

Debug.Assert(__refvalue(synonym, string) == text); 

現在,讓我們更改文本到一個新值:

text = "second value"; 
Debug.Assert(__refvalue(synonym, string) == text); 

而且即使相反也是如此:

__refvalue(synonym, string) = "third value"; // <--- 
Debug.Assert(__refvalue(synonym, string) == text); 

最後讓我們來修改另一個函數中的原始變量(不知道它會看到一個正常變量的引用):

void ChangeIt(ref string value) { value = "another value"; } 

ChangeIt(ref text); 
Debug.Assert(__refvalue(synonym, string) == text); 

所有這一切工作將值類型爲好。請注意,這會爲變量創建一個同義詞,而不是別名(您可以將它們想象爲一個安全指針 - 指向引用類型的指針)。讓我們試試這個:

void foo1() 
{ 
    string text = "ABC"; 
    foo2(text); 

    // text holds the original value "ABC" 
    // not the value modified in foo2 
} 

void foo2(string value) 
{ 
    value = "123"; 
    var synonym = __makeref(value); 
    __refvalue(value, string) = "456"; 

    // both value and synonym holds "456"; 
} 
+1

完全不提高可讀性,但它回答了這個問題。我很高興瞭解這些(即使我不會真正使用它們)。 – Serge

+0

@Serge是的我不會建議在任何真正的程序中使用它們(不僅僅是因爲它們沒有記錄)。我從來沒有覺得我需要C#中的這個特性(同義詞),但是...這是我能想象到的第一個真正用於關鍵字的東西!大聲笑 –

5

如果你真的很需要這一點,你可以這樣做以下,但我認爲它仍然是跛腳(:

class RefHolder<T> 
{ 
    public RefHolder(T value) 
    { 
     Value = value; 
    } 

    public T Value { get; set; } 
} 

使用

var o1 = new RefHolder<object>(new object()); 
var o2 = o1; 
o2.Value = null; // now o1.Value is null too 
+1

他說寫道:o1 = null並且o2自動變爲null。 – Tigran

+0

我明白了,這就是爲什麼這仍然是跛腳。 –

+0

@Tigran,我很高興有替代方案的建議。 – Serge

0

這取決於.NET包含兩個參考和。值類型:值類型都是基本類型,整型,布爾等。加上字符串。引用類型的一切,包括你所建立的自己。

因此,例如,值類型...

int a = 3; 
int b = a; 
b = 5; 
// a is still 3 

雖然與引用

class Mine { 
    public int A { get; set; } 
} 
Mine A = new Mine() { A = 3; } 
Mine B = A; 
B.A = 5; 
// A.A is now 5. 
+2

問題是另一個。 –

+0

我的意思是不,synonims本身不存在,但可以通過使用引用變量而不是值類型來實現。對不起,如果沒有遇到。 –

+0

這與穆罕默德早些時候給出的答案略有相同,但用較少的友好命名。 – Serge

-1

你可以像ASIGN

var parentObject={}; 

parentobject['child1']="test1"; 
parentobject['child2']="test2"; 
parentobject['child3']="test3"; 

的console.log(parentObject);

你得到以下輸出

對象{child1 = 「測試1」,的child2 = 「test2的」,的child2 = 「test2的」}

+1

這是一個JavaScript的答案? – Serge

+1

您在錯誤的問題中粘貼了您的代碼... –

1

那麼,你正在basicly描述一個C++參考(或C指針)。 這也可以用C#來完成,但是除非你絕對需要,否則你真的不想這樣做。

unsafe static void Main(string[] args) 
    { 
     int a = 5; 

     int *b = &a; 
     *b = 0; 

     Console.WriteLine(a); 
    } 

這將輸出0到控制檯。

您可以在MSDN上Unsafe Code and Pointers文章閱讀更多關於不安全的代碼。

+2

在C#中,您不能擁有指向類的指針,因此此方法僅適用於某些非託管類型。要查看哪些類型可能是指針類型,可以查看[指針類型(C#編程指南)](http:// msdn。microsoft.com/en-us/library/y31yhkeb.aspx)來自MSDN。 –