c#引用数组

本文关键字:数组 引用 | 更新日期: 2023-09-27 18:08:56

我该怎么做呢?

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;
}
编辑:

我想这样做是因为这些变量可以被其他类直接访问。比如v1可以是某物的宽度v2可以是某物的高度。我的一些类使用width变量来限制必须从用户处获取的输入的长度。有些类使用height变量来做其他事情。但是我希望能够使用循环来编辑这些变量因为现在编辑过程是这样的
int indexOfVarToChange = GetIndex ();
switch (indexOfVarToChange) {
    case 0:
        int newValue = GetNewValue ();
        width = newValue;
        break;
    case 1:
        int newValue = GetNewValue ();
        height = newValue;
        break;
}

我必须手动重新分配变量,因为我不能在循环中使用这些变量的引用数组。我有超过30个唯一的变量,我必须这样做,这是一个痛苦的。

我想后备计划是将所有这些变量移动到Dictionary中,并拥有所有键的数组,并将每个键传递给编辑函数。

c#引用数组

不行

你仍然可以编辑这些元素,但是只能直接赋值给它们:

 vars[2] += 42;

但我刚刚测试了这个工作:

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]);
        }
}

生活http://ideone.com/fz36y

输出
3
42
<<h2>更新:包装器/h2>

作为一种脑力练习,我想出了这种令人恶心的扭曲机制,仍然可以得到你想要的东西(但比简单地把所有int都打包起来要付出更多的代价):

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
}

现在,Wrap<int>将大致表现为一个普通的int(需要在比较,相等和运算符领域做更多的工作)。你可以用它来写这个,并让它按照你想要的方式工作:

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();
}
输出:

7
42

生活:http://ideone.com/b0m7T

假设您真的确实需要做这样的事情,我认为在不使用不安全代码的情况下,最接近的方法是更改代码,通过创建一个小类Holder来"保存"int(或任何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;
      }
    }
  }
}

这个类的InitializeAll方法使用Linq表达式和反射来工作。我想这和你想要的代码的意图是一样的。将v1、v2、v3和v4分别初始化为0、1、2和3。

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);
            }
        }
    }
}