2013-06-19 2 views
0

То, что я пытаюсь сделать, это иметь массив ссылок на переменные. Под этим я подразумеваю эквивалент C массива указателей на ints (например).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 

Специфика моего случая: У меня есть список строк, которые будут соответствовать ключей в словаре. Я думаю, что я хочу иметь список Tuples, где Type1 является ссылкой на int или string, а Type2 - ссылкой на текстовое поле.

Я буду повторять этот список, используя строку, чтобы получить значение из словаря (и делать материал с этими данными), а затем сохранить результаты этого в Type1. И в итоге я возьму данные из этих переменных типа Type1 и скопирую их данные в соответствующий текстовый ящик Type2.

Это суть того, что я думаю, что я хочу сделать. Если кто-то думает, что мой подход слишком сложный, я скажу, что мне нужно сохранять текстовые поля, как это печально, поэтому я не могу просто создать массив и прокрутить его. И было бы удобно хранить переменные Type1 отдельно, хотя и не совсем так необходимо.

Теперь, начиная с чтения, я думал, что Func <> выглядел так, будто это было самым близким к тому, чтобы быть полезным для того, что я хочу, поэтому я попытался использовать следующее (с Type1, как объект, потому что ему нужно обрабатывать как ints и строки)

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

но я не знал, как использовать это, чтобы получить ссылки на переменные.

+0

«If кто-то думает, что мой подход слишком сложный, я скажу, что мне нужно сохранять текстовые поля, как они грустно, поэтому я не могу просто создать массив и прокрутить его ». - Что это значит? –

+0

вы можете использовать указатели в этом случае, используйте небезопасное ключевое слово для метода и задайте небезопасный проект, чтобы разрешить указатели в 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, чтобы автоматически установить значение TextBox. Но это, надеюсь, даст вам общее представление о том, как что-то подобное делается в стиле OO.

EDIT Вот как будет выглядеть ваш пример.

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» является классом (и, следовательно, ссылочным типом), тогда изменение свойства или любой другой информации о конкретном экземпляре будет отображаться в любом месте программы, имеющей доступ к этому экземпляру. Другими словами, он будет делать то, что вы хотите.Вы можете найти [это] (http://www.yoda.arachsys.com/csharp/parameters.html) интересным. Хотя он специально предназначен для передачи параметров, информация в нем истинна для всех переменных. –

+0

и то же самое относится к значению только потому, что его в этом классе? – 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; 
} 

Таким образом, мы вернулись в ValueWrapper из test(), который, по-видимому оберточной локальную переменную внутри теста(). И тогда мы можем изменить значение и распечатать его ...

Это не совсем то, что происходит, конечно, но это может быть довольно запутанным!

+0

+1, хотя мне любопытно, почему делегаты 'get' и' set' (а не просто сохраняют значение в переменная экземпляра) –

+0

@AdamRobinson Поскольку я специально хотел изменить исходное значение, то есть значение 'x' в стеке в методе' test() '. Обратите внимание, как значение 'x' действительно изменяется, когда мы вызываем метод' test() ', который делает его * отображаемым *, как если бы ссылка' x' каким-то образом использовалась внутри 'test()'. Магия захваченных переменных. :) –

+0

Я знаю, что могут сделать замыкания, но учитывая, что на самом деле (в действительности) выполняется то же самое (создание класса для размещения локальной переменной, а затем замена каждого доступа локальной переменной после закрытия с доступом свойства на экземпляре этого класса), но без накладных расходов на вызов делегата, я действительно не вижу преимущества. На самом деле нет волшебства :) –

0

вы можете использовать указатели в этом случае использовать небезопасный ключевое слово метод и установить проект небезопасным, чтобы указатели в C#, а также вы можете инкапсулировать значение в классе и в C# каждый класс ссылочного типа

Смежные вопросы