簡體   English   中英

C#引用數組

[英]C# Array of references

我怎么能這樣做?

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個獨特的變量,我必須這樣做,這是一個痛苦。

我想回退計划是將所有這些變量移動到一個字典中,並擁有一個包含所有鍵的數組,並將每個鍵傳遞給編輯函數。

你不能。

您仍然可以在適當的位置編輯元素,但只能直接指定它們:

 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

更新:包裝

作為一項心理鍛煉,我想出了這種生病和扭曲的機制,仍能得到你想要的東西(但是比簡單地裝箱所有的東西更加昂貴):

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

假設為參數的緣故,你真的需要做這樣的事情,我覺得你可以不使用不安全的代碼最接近的是要改變你的代碼通過使一個小類持有人,其“持有”整數加一個間接層(或任何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);
            }
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM