2011-03-10 82 views
7

基本上我希望能夠有一個類的實例內的變量的引用,但我希望引用成爲一個類變量,所以我不需要把它周圍的類內的參數c#:從類的構造函數保留ref參數

代碼:

int num = 0; 
myClass(num); 
print num; // output is 0 but i'd like it to be 10 :) 
class myClass 
{ 
    private int classNumber; 
    myClass(ref int number) 
    { 
     print number; //output is 0 

     // id like this to be a reference to the refenrence 
     classNumber = number; 

     DoSomething(); 
    } 
    public void DoSomething() 
    { 
     ClassNumber = 10; 
    } 
} 

爲什麼我問這是因爲我用的WinForms工作,具有主窗體發送一個類的實例,以新窗體應該編輯類並將其發回..現在我使用Form.ShowDialog()來避免用戶在使用新窗體進行編輯時使用主窗體,來自新表格的數據

editForm edtfrm = new editForm(ref instanceOfClass); 
edtfrm.showDialog(); 
//grab the instance back 
instanceOfClass = edtfrm.editedClass; 

我該如何解決這個問題?我不喜歡這個解決方案

+0

你的兩個問題似乎完全無關。你確定問題1的解決方案將幫助你解決問題2嗎? – Heinzi 2011-03-10 14:39:17

+0

「問題2」就是我如何解決這個困境atm ..通過創建一個我參考的副本,然後當我完成編輯它複製回來,在問題1,如果我做「classNumber」公開和打印之前我會做'NUM = myClass.classNumber' – Tistatos 2011-03-10 14:45:43

+2

由於'instanceOfClass'是一個參考,你並不需要使用'ref'傳遞給它(因爲你想改變*內容*'的instanceOfClass',沒有指針本身)。我也不明白爲什麼你必須「搶回實例」... instanceOfClass和editedClass仍然應該指向內存中的同一個對象,不是? – Heinzi 2011-03-10 15:08:51

回答

0

創建一個包含你的號碼作爲一個屬性的類,並通過你的邏輯傳遞它。該班將代表你的「模特」。

0

您不能保存ref參數,ref不是參考,它只是一個alias。如果您有:

public void Stuff (ref int i) 
{ 
    i = 2; 
} 

,並稱之爲:

int s = 1; 
Stuff(ref s); 

ref的意思是「讓我對於s的別名和傳播的變化吧。」一旦你離開了方法的範圍,那個別名就消失了。有意思的是,Eric Lippert在他的blog上開了一個系列。

你應該創建一個類並在你的邏輯中使用它。 GUI不應該操縱值,只有後端應該。

0

這裏有一些東西。 首先,在你的構造函數,你可能想要做

DoSomething();  
number=classnumber; 

,而不是

classnumber=number; 

其次,儘量

myClass(ref num); 

,而不是

myClass(num); 
+0

我在帖子中加了'ref';)。這可以爲我提出問題的方式工作。然而我的問題在於一個winforms,所以我不能像我一樣在構造函數中做所有的編輯。因爲新窗體在另一個線程中,我需要在整個新窗體中保留該引用 – Tistatos 2011-03-10 14:50:06

2

這不是一個真正的好想法是什麼y歐正在嘗試做的,我會暴露修改的對象爲類的屬性如下圖所示:

public class ClassContructorReference 
{ 
    static void Main(string[] args) 
    { 
     object var = new object(); 
     MyClass myClass = new MyClass(var); 
     StringBuilder mySb = myClass.Instance as StringBuilder; 
     Console.WriteLine(mySb.ToString()); 
    } 
} 

public class MyClass 
{ 
    public object Instance {get;set;} 

    public MyClass(object var) 
    { 
     this.Instance = var; 
     DoSomething(); 
    } 

    private void DoSomething() 
    { 
     this.Instance = new StringBuilder("Hello"); 
    } 
} 
14

我想能有一個類的實例裏面一個變量的引用,但我想參考成爲一個類變量,所以我不需要發送它在班級裏面作爲參數

你將不得不忍受那麼失望。 CLR類型系統明確禁止將變量引用存儲爲類的成員。在CLR允許引用變量是

  • 傳遞給方法的相應正式參數或參數「本」
  • 存儲爲當地人
  • 返回方法的返回值

但確實而不是允許存儲數組,字段等。基本上,任何「在堆上」的東西都不能成爲裁判。

C#暴露第一特徵:參變量作爲方法參數。它沒有公開其他兩個特性(儘管我已經寫了一個C#的實驗版本,它的工作原理相當不錯)。

請注意,C#不允許在上下文中使用refs,這需要堆存儲例如,ref就像一個ref參數,它是一個lambda的封閉外部變量。在少數情況下,編譯器確實允許看起來像ref的長期存儲,並使用copy-in-copy-out語義來模擬ref,但最好甚至不要去那裏。

爲什麼CLR這個限制?正確的思考方式是有兩種存儲方式:長期和短期,通常稱爲「堆」和「堆棧」。但是數據結構的形狀是不相關的;什麼是相關的是生命的長度。變量具有存儲位置;這是一個變量。如果您可以在長期存儲中保留對從短期存儲分配的變量的引用,那麼長期存儲將保留對壽命較短的引用,因此可能會在訪問變量時崩潰並死亡死後。

顯然有很多辦法來解決這個問題。例如,CLR團隊可能會選擇將短期存儲作爲參考,並允許長期存儲參考。但是那意味着你不能把局部變量或參數作爲參考,因爲它們的壽命太短,你想把它放在短期存儲器中。

的CLR團隊實際上選擇的辦法是禁止任何裁判的長期儲存。像任何設計決策一樣,這是對競爭目標進行許多折衷的結果。

1

Ofcourse你的測試代碼不會因爲它的工作是一種原始的type.but你的第二代碼將工作,因爲它是一個引用類型。(不需要連「裁判」)無需實例分配回來。

public class Second 
{ 
    public First f; 

    public Second(First f) 
    { 
     this.f= f; 
    } 

    public void change() 
    { 
     this.f.Name = "PUli"; 
    } 
} 
public class First 
{ 
    private string _name; 

    public First() 
    { 
     Name = "SUli"; 
    } 

    public string Name 
    { 
     get { return _name; } 
     set { _name = value; } 
    } 
} 
class Program 
{ 
    static void Main(String[] args) 
    { 
     First f = new First(); 
     Second sec = new Second(f); 
     Console.WriteLine(f.Name); 
     sec.change(); 
     Console.WriteLine(f.Name); 
    } 
} 

輸出: -

蘇力

埔里