如何在C#数组中引用一个值

3

i have the following array :

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

并引用第二个元素,如下所示:

int rr = myArray[1];

i want something like : rr = 500

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

我希望你们能理解我的想法,我可以像上面的例子一样轻松地在Python中完成这个任务。 那么,在C#中如何实现呢?

你怎么可能期望myArray中有值为500的元素,而实际上却没有呢? - Yahia
500 是从哪里来的?你的例子中没有 500,它是某种求和吗? - balexandre
3
@MoayyadYaghi似乎想做类似于数组元素指针的东西,所以rrmyArray[1]的别名。 - Zbigniew
2
@MoayyadYaghi 那么您可以考虑阅读:如何使用指针访问数组元素(C#编程指南) - Zbigniew
1
你这么做的原因是什么?你为什么要这样做? - svick
显示剩余6条评论
6个回答

5
我的解决方案可能是创建一个以arr[1]作为其支撑属性的属性。

类似这样:

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

然后 rr=500; 将与 arr[1]=500; 相同


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

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++编写代码并将其作为dll导入,然后你就有了良好的关注分离,不要忘记进行测试驱动开发!)

实际上,在C#中几乎所有东西都是指针,而不是引用。所有属于 class 的内容都是如此。int 是一个结构体,因此存在问题。 - Agent_L
int是一个不可变的值类型(http://msdn.microsoft.com/en-us/library/s1ax56ch.aspx)。虽然Int32是一个结构体,但这不应与int值类型混淆。 C#默认使用引用,你只能在unsafe上下文中使用指针(http://msdn.microsoft.com/en-us/library/490f96s2.aspx)。 - Molibar
我的意思是,由于Application foo = null;,它们的行为更像指针而不是引用(在C++中的意义)。唯一真正的、不可变的引用是ref和out函数参数。 - Agent_L

1

只需使用myArray[1] = 500!如果您特别想要引用数组中特定整数的属性,可以像Nahum Litvin建议的那样使用属性。


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选项进行编译。

我希望你能看到这可能会带来一些问题。
因此,我不建议使用这种解决方案


我对此不是很了解,但当我在没有fixed-stmt的情况下尝试时,编译器会给出以下错误:You can only take the address of an unfixed expression inside of a fixed statement initializer - Johannes Egger

1
你需要的基本上是一个指向变量的指针。 很难解释“值类型”(如intstruct)、引用和指针之间的区别。我只能建议学习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

是的,这很复杂,但我怀疑如果没有不安全的代码,就无法简化它。对于没有解释得更多我感到抱歉。我会在评论中回答所有问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接