2013-06-19 61 views
0

我想要做的是對變量的引用數組。我的意思是相當於一個指向整數的C數組(例如)。C#對變量和/或表單對象的引用數組

實例:(!!不是真正的代碼!)

int a = 4; 
int b = 5; 
int c = 6; 
List<ref int> tmp = new List<ref int>(); 

tmp.Add(ref a); 
tmp.Add(ref b); 
tmp.Add(ref c); 

tmp[0] = 16; 
tmp[1] = 3; 
tmp[2] = 1000; 

Console.Writeline(tmp[0] + " " + a); // 16 16 
Console.Writeline(tmp[1] + " " + b); // 3 3 
Console.Writeline(tmp[2] + " " + c); // 1000 1000 

我的情況的細節:我有一個將對應於在字典中鍵的字符串列表。我想我想要的是一個元組列表,其中Type1是對int或字符串的引用,Type2是對Textbox的引用。

我將迭代通過此列表,使用字符串從字典中獲取值(並使用該數據進行處理),然後將結果存儲到Type1中。最終,我將從這些Type1變量引用中獲取數據,並將其數據複製到相應的Type2文本框中。

這就是我想要做的事情的要點。如果有人認爲我的方法過於複雜,我會說我需要保持文本框的可悲性,所以我不能只是製作一個數組並迭代它。儘管不是非常必要,但仍然可以保持Type1變量的獨立性。我認爲Func <>看起來最接近於對我所需要的東西有用,所以我嘗試使用以下內容(使用Type1作爲對象,因爲它需要同時處理這兩個對象)整數和字符串)

List<Tuple<string, Func<object>, Func<object>>> 

但我不確定如何使用它來獲得對變量的引用。

+0

「如果有人認爲我的方法過於複雜,我會說我需要保留文本框,因爲它們很可悲,所以我不能只是製作一個數組並迭代它。「 - 這是什麼意思? –

+0

你可以在這種情況下使用指針,使用unsafe關鍵字的方法和設置項目不安全,以允許在C#中的指針,也可以封裝在一個類中的值,並在C#中每個類是引用類型 – ahmedsafan86

+0

@Ahmedsafan:雖然我不同意您建議的建議,應該是答案,而不是評論。 –

回答

3

你是什麼特別是要求是不可能的;什麼更合適(並且有實際工作的便利!)將是圍繞你想要做的事情設計一個班級結構。

舉例來說,這樣的事情:

public class MyObject // Name it appropriately 
{ 
    public object Value { get; set; } 
    public string Key { get; set; } 
    public TextBox TextBox { get; set; } 
} 

然後,在你的代碼,你可以做一個類似於此...

Dictionary<string, object> values = ... 
List<MyObject> objects = ... 

foreach(var item in objects) 
{ 
    item.Value = values[item.Key]; 

    // process your data 

    item.TextBox = item.Value.ToString(); 
} 

顯然,這只是一個粗略的設計和這裏的課程僅僅是一個數據傳輸容器。例如,您可以通過使用Value屬性的setter自動設置TextBox的值來使課程變得「更智能」。但是,這應該有希望給你一個這樣的東西如何以面向對象的方式完成的一般想法。

編輯下面是您的示例的外觀。

MyObject a = new MyObject() { Value = 4 }; 
MyObject b = new MyObject() { Value = 5 }; 
MyObject c = new MyObject() { Value = 6 }; 
List<MyObject> tmp = new List<MyObject>(); 

tmp.Add(a); 
tmp.Add(b); 
tmp.Add(c); 

tmp[0].Value = 16; 
tmp[1].Value = 3; 
tmp[2].Value = 1000; 

Console.Writeline(tmp[0].Value.ToString() + " " + a.Value.ToString()); // 16 16 
Console.Writeline(tmp[1].Value.ToString() + " " + b.Value.ToString()); // 3 3 
Console.Writeline(tmp[2].Value.ToString() + " " + c.Value.ToString()); // 1000 1000 
+0

如果當我創建一個MyObject,並將該文本框設置爲等於表單上的一個現有的Texbox,那麼將textbox.Text屬性設置爲某個值,並更新表單上的任何內容,那麼這正是我想要的。如果沒有,我不知道這將如何幫助 – DanielCardin

+0

@DanielCardin:是的,它會。作爲一個'TextBox'是一個類(因此是一個引用類型),那麼改變一個屬性或任何其他特定於實例的信息將在可以訪問這個實例的程序中的任何地方可見。換句話說,它會做你想做的。你可能會發現[this](http://www.yoda.arachsys.com/csharp/parameters.html)很有趣。雖然它專門針對參數傳遞,但其中的信息對所有變量均爲真。 –

+0

並且同樣適用於Value,僅僅因爲它在這個類中? – DanielCardin

1

您不能使用C#存儲引用。調用方法時,只能使用ref關鍵字。

可以使用指針,但你只能做與fixed表達和unsafe範圍內。

有可能使用委託來僞造這種類型的東西,但我不確定它是否是您要找的東西。我也相當肯定,你真的需要重新設計你的方法,但儘管如此,這裏有一個如何可以假的吧...

首先,寫了一個「值包裝」類,像這樣的例子:

public class ValueWrapper<T> 
{ 
    readonly Func<T> get; 
    readonly Action<T> set; 

    public ValueWrapper(Func<T> get, Action<T> set) 
    { 
     this.get = get; 
     this.set = set; 
    } 

    public T Value 
    { 
     get 
     { 
      return get(); 
     } 

     set 
     { 
      set(value); 
     } 
    } 
} 

然後,你可以用它來改變值:

void run() 
{ 
    int x = 0; 

    var intWrapper = new ValueWrapper<int>(() => x, value => x = value); 

    test(intWrapper); 

    Console.WriteLine(x); // Prints 42, which shows that x was changed. 

    TextBox textBox = new TextBox {Text = ""}; 

    var stringWrapper = new ValueWrapper<string>(() => textBox.Text, value => textBox.Text = value); 

    test(stringWrapper); 

    Console.WriteLine(textBox.Text); // Prints "Changed". 
} 

static void test(ValueWrapper<int> wrapper) 
{ 
    wrapper.Value = 42; 
} 

static void test(ValueWrapper<string> wrapper) 
{ 
    wrapper.Value = "Changed"; 
} 

您也可以在一個方法創建一個包裝,並把它傳遞給它使用包裝原包裝的對象更改屬性不同的方法,如所以:

void run() 
{ 
    TextBox textBox = new TextBox {Text = ""}; 

    var wrapper = test1(textBox); 
    test2(wrapper); 
    Console.WriteLine(textBox.Text); // Prints "Changed" 
} 

void test2(ValueWrapper<string> wrapper) 
{ 
    wrapper.Value = "Changed"; 
} 

ValueWrapper<string> test1(TextBox textBox) 
{ 
    return new ValueWrapper<string>(() => textBox.Text, value => textBox.Text = value); 
} 

警告:這確實導致了一些相當頭刮代碼,例如:

void run() 
{ 
    var intWrapper = test(); 
    intWrapper.Value = 42; 
    Console.WriteLine(intWrapper.Value); // Works, but where is the value? It can't be the x inside test()! 
} 

ValueWrapper<int> test() 
{ 
    int x = 0; 
    var intWrapper = new ValueWrapper<int>(() => x, value => x = value); 
    return intWrapper; 
} 

等我們回到從test()一個ValueWrapper這顯然是從內部測試包裝的局部變量()。然後,我們可以顯然改變價值和打印出來...

這當然不是真的發生了什麼,但它可以是相當混亂!

+0

+1添加一個添加方法,但我很好奇爲什麼'get'和'set'委託(而不是僅僅存儲值一個實例變量) –

+0

@AdamRobinson因爲我特別想在'test()'方法中改變原始值,即堆棧中'x'的值。請注意,當我們調用test()方法時,'x'的值實際上會發生變化,這使得*出現*好像在'test()'內部已經使用了'x'的引用。捕獲變量的魔力。 :) –

+0

我知道閉包可以做什麼,但考慮到它實際上(現實中)做同樣的事情(創建一個類來容納局部變量,然後在關閉後用局部變量替換每個局部變量的訪問的屬性在該類的一個實例上),但沒有委託調用的開銷,我沒有真正看到優勢。實際上,沒有魔法:) –

0

可以在這種情況下使用指針,使用方法不安全不安全關鍵字和設置項目,以允許在c#指針,還可以封裝該值在類,並在C#每個類是引用類型