2013-06-19 31 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#每个类是引用类型