C # Array of links

How can I do something like this?

int v1 = 4; int v2 = 3; int v3 = 2; int v4 = 1; int [] vars = new int [] {ref v1, ref v2, ref v3, ref v4}; for (var i = 0; i < 4; i++) { ChangeVar (vars [i], i); } void ChangeVar (ref int thatVar, int newValue) { thatVar = newValue; } 

Edit:

I want to do this because other classes access these variables directly. For example, v1 may be the width of something, and v2 may be the height of something. Some of my classes use a width variable to limit the length of the input that it should receive from the user. Some classes use a height variable to do something else. But I want to be able to edit these variables using a loop, because right now the editing process works like this:

 int indexOfVarToChange = GetIndex (); switch (indexOfVarToChange) { case 0: int newValue = GetNewValue (); width = newValue; break; case 1: int newValue = GetNewValue (); height = newValue; break; } 

I need to reassign variables manually because I cannot have an array of references to these variables that will be used in the loop. I have over 30 unique variables that I have to do for this, and this is a pain.

I think that the backup plan would be to move all these variables to the dictionary and have an array of all the keys and pass each key to the editing function.

+6
source share
3 answers

No, you can’t.

You can still edit items in place, but only by assigning them directly:

  vars[2] += 42; 

But I just tested this:

 using System; public class Test { private static void assign(ref int i) { i = 42; } public static void Main() { var vars = new [] { 1,2,3,4 }; Console.WriteLine(vars[2]); assign(ref vars[2]); Console.WriteLine(vars[2]); } } 

See LIVE http://ideone.com/fz36y

Exit

 3 42 

Update: Wrapper

As a mental exercise, I came up with this sick and twisted mechanism to still get what you want (but at an even higher price than just boxing all the ints):

 private class Wrap<T> where T : struct { public T Value; public static implicit operator Wrap<T>(T v) { return new Wrap<T> { Value = v }; } public static implicit operator T(Wrap<T> w) { return w.Value; } public override string ToString() { return Value.ToString(); } public override int GetHashCode() { return Value.GetHashCode(); } // TODO other delegating operators/overloads } 

Now Wrap<int> will behave roughly like a regular int (more work is needed in the areas of comparison, equality, and operators). You can use it to write this, and work the way you wanted:

 private static void assign(ref int i) { i = 42; } public static void Main() { Wrap<int> element = 7; var vars = new Wrap<int>[] {1, 2, element, 3, 4}; Console.WriteLine(vars[2]); assign(ref vars[2].Value); Console.WriteLine(element); Console.ReadKey(); } 

Conclusion:

 7 42 

Check out live: http://ideone.com/b0m7T

+3
source

Assuming for the sake of argument that you really need to do something, I think the closest you can do without using unsafe code is to modify your code to add an indirect level by making a small Holder class that "contains" ints (or any T )

 namespace ConsoleApplication33 { public static class Program { private static void Main() { var t1=new Holder<int>(4); var t2=new Holder<int>(3); var t3=new Holder<int>(2); var t4=new Holder<int>(1); var vars=new[] {t1, t2, t3, t4}; for(var i=0; i<4; i++) { ChangeVar(vars[i], i); } } static void ChangeVar<T>(Holder<T> thatVar, T newValue) { thatVar.Value=newValue; } public class Holder<T> { public T Value { get; set; } public Holder(T value=default(T)) { Value=value; } } } } 
+1
source

The InitializeAll method of this class works using Linq expressions and reflection. I think this is the same intention as the code. It initializes v1, v2, v3, and v4 to 0, 1, 2, and 3, respectively.

 using System; using System.Linq.Expressions; namespace ArrayOfReferences { public class InitializeMultipleVariables { int v1; int v2; int v3; int v4; public void InitializeAll() { Initialize( () => v1, () => v2, () => v3, () => v4); } public void Initialize(params Expression<Func<int>>[] intExpressions) { for (int i = 0; i < intExpressions.Length; i++) { var expr = intExpressions[i].Body as System.Linq.Expressions.MemberExpression; var fieldInfo = this.GetType().GetField(expr.Member.Name, System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); fieldInfo.SetValue(this, i); } } } } 
0
source

Source: https://habr.com/ru/post/897615/


All Articles