3

我有以下数组:

int[] myArray = {21,21,364,658,87};

以及对第二个元素的引用,如下所示:

int rr = myArray[1];

我想要类似的东西: rr = 500

Console.writeLine(myArray[1]);// ---> should print 500 !

我希望你们明白我的想法,我可以像上面的例子一样在 python 中轻松地做到这一点。那么
如何在 C# 中做到这一点

4

6 回答 6

5

我的解决方案可能是创建属性arr[1]作为其支持属性

就像是:

  public int rr
  {
    set{ arr[1] = value;}
    get{ return arr[1];}
  }

而比rr=500;将与arr[1]=500;

于 2012-09-09T11:11:22.787 回答
4

你可以使用这样的东西:

public static class ArrayExtensions
{
    public static Action<int> CreateSetter(this int[] array, int index)
    {
        return (value) => array[index] = value;
    }
}

[TestFixture]
public class ArrayTest
{
    [Test]
    public void Test()
    {
        int[] myArray = {21,21,364,658,87};
        Action<int> rr = myArray.CreateSetter(1);
        rr(500);
        Assert.AreEqual(500, myArray[1]);
    }
}
于 2012-09-09T11:07:24.530 回答
2

当你这样做时:

int[] myArray = {21,21,364,658,87};
int rr = myArray[1];
rr = 500;

您只会覆盖 rr 中的值,您无法获取数组内部元素的实际内存地址,从而对其进行更新。

因此,我的回答必须是:

myArray[1] = 500;

我试图理解你想要做什么,如果你想将你的更改封装在一个函数中,你可以通过这种方式传递引用,但这完全取决于你想用它做什么:

    public void Proc()
    {
        var ints = new [] { 1, 2, 3, 4 };
        FunctionChangingByReference(ref ints[1]);
    }

    public void FunctionChangingByReference(ref int x)
    {
        x = 500;
    }

在 C# 中没有指针,只有引用。

(我有点撒谎,如果你创建一个不安全的上下文,你可以使用指针,但我们不会在 C# 中这样做,你也不应该这样做。当我们编写 C++ 代码时,我们会这样做,但那是 C++,我们在成本,我们使代码更脆弱和容易出错。当我编写 C# 代码时,我尝试在比内存地址改组更高的级别上优化代码。如果你真的需要在那个级别上进行优化,你应该用 C++ 编写代码并将该代码作为 dll 导入,然后您就可以很好地分离关注点,并且不要忘记试驾开发!)

于 2012-09-09T11:47:23.167 回答
1

简直了myArray[1] = 500!如果您特别想要引用数组中的特定整数,则可以使用 Nahum Litvin 建议的属性。

于 2012-09-09T11:13:49.780 回答
1

你想要的是一个基本上指向变量的指针。很难解释“值类型”(如intor struct)、引用和指针之间的区别。我只能推荐学习C。

这是可行的解决方案,尽管它可能需要对您的代码进行大量更改。

//a class that will hold an int inside
public class myIntWrapper
{
    //this is the value wrapper holds
    public int theValue;
    //constructor taking the value
    public myIntWrapper(int argument)
    {
        theValue = argument;
    }

    //operator to convert an int into brand-new myIntWrapper class
    public static implicit operator myIntWrapper(int argument)
    {
        return new myIntWrapper(argument);
    }

    //operator to convert a myIntWrapper class into an int
    public static implicit operator int(myIntWrapper wrapper)
    {
        return wrapper.theValue;
    }
}

现在你可以写:

//create an array -
//setting values to every item in array works 
//thanks to operator myIntWrapper(int argument)
myIntWrapper[] myArray = new myIntWrapper[5]{1,2,3,4,5};

//now take a "reference"
myIntWrapper rr = myArray[1];

//change the value
rr.theValue = 500;
//from now on myArray[1].theValue is 500;

//thanks to operator int(myIntWrapper wrapper)
//you can write:
int ss = rr;//it works!

请记住永远不要这样做: rr = 600; 因为这实际上会创建全新的 myIntWrapper,它不会在任何地方“连接”。所以请记住:

rr.theValue = 500;//this changes the value somewhere
rr = myArray[3];//this changes where rr is "pointing" to

是的,这很复杂,但我怀疑如果没有不安全的代码,它可以做得更简单。我很抱歉没有更多地解释它。我会在评论中回答所有问题。

于 2012-09-10T12:10:23.873 回答
1

@des 的回答引起了我的兴趣。所以我尝试了他的解决方案,它按预期工作:

int[] numbers = new[] { 1, 2, 3 };
fixed (int* number = &numbers[0])
{
  *number = 10;
}
Console.WriteLine(String.Join(", ", numbers)); // Outputs "10, 2, 3"

您必须使用该/unsafe选项编译它。

我希望你看到这可能会带来一些问题。
因此我不推荐这个解决方案

于 2012-09-09T11:24:22.797 回答