3 回答

TA貢獻1828條經(jīng)驗 獲得超6個贊
正如其他人所指出的那樣,你不能擁有“ref to variable”類型的字段。然而,只知道你不能做到這一點可能并不令人滿意; 你可能也想先知道,為什么不知道,其次,如何解決這個限制。
原因是因為只有三種可能性:
1)禁止ref類型的字段
2)允許ref類型的不安全字段
3)不要將臨時存儲池用于局部變量(也稱為“堆棧”)
假設(shè)我們允許ref類型的字段。然后你可以做到
public ref int x;void M(){ int y = 123; this.x = ref y;}
現(xiàn)在可以在M
完成后訪問y 。這意味著要么我們遇到(2) - 訪問this.x
將崩潰并且死亡可怕因為y的存儲不再存在 - 或者我們遇到(3),并且本地y
存儲在垃圾收集堆上,而不是臨時內(nèi)存池。
我們喜歡將局部變量存儲在臨時池中的優(yōu)化,即使它們是由ref傳遞的,我們也不喜歡你可能會留下定時炸彈,這可能會導(dǎo)致程序崩潰并在以后死亡。因此,選項一是:沒有引用字段。
注意,對于作為匿名函數(shù)的封閉變量的局部變量,我們選擇option(3); 這些局部變量不會從臨時池中分配出來。
這就引出了第二個問題:你如何解決這個問題?如果你想要一個ref字段的原因是制作另一個變量的getter和setter,那就完全合法了:
sealed class Ref<T>{ private readonly Func<T> getter; private readonly Action<T> setter; public Ref(Func<T> getter, Action<T> setter) { this.getter = getter; this.setter = setter; } public T Value { get { return getter(); } set { setter(value); } }}...Ref<int> x;void M(){ int y = 123; x = new Ref<int>(()=>y, z=>{y=z;}); x.Value = 456; Console.WriteLine(y); // 456 -- setting x.Value changes y.}
你去吧 y
存儲在gc堆上,x
是一個能夠獲取和設(shè)置的對象y
。
請注意,CLR確實支持ref本地和ref返回方法,但C#不支持。也許C#的假設(shè)未來版本將支持這些功能; 我有它的原型,它運作良好。但是,這在優(yōu)先級列表中并不是很高,所以我不會抱有希望。
更新:上面段落中提到的功能最終在C#7中實現(xiàn)了。但是,您仍然無法在某個字段中存儲引用。
- 3 回答
- 0 關(guān)注
- 533 瀏覽
添加回答
舉報