在C#中,是否可以通过引用使用foreach迭代int数组?

5

在C#的foreach循环中,是否可以通过引用迭代int数组?

我的意思是这样的:

 int[] tab = new int[5];
 foreach (ref int i in tab)
 {
     i=5;
 }

谢谢


2
这个能编译吗?int[] tab = new tab[5]; 你为什么要这么做呢? - DvS
你为什么想要这样做? - Oluwafemi
tab[i] = 5;有什么问题吗?只需使用常规的for循环或编写一个简单的扩展方法,返回一个KeyValuePair即可。 - Dennis_E
你可能想看一下 for 循环。 - decPL
Enumerable.Range(1,5).Select(x=>5).ToArray() 有什么缺点吗? - DarkSquirrel42
4个回答

3
自C# 7.3版本开始,它可以工作,但您需要将数组强制转换为Span。
int[] tab = new int[5];

foreach (ref int i in tab.AsSpan()) {
    i = 5;
}

Console.WriteLine(tab.Sum()); // 25

已在Net Core 3.1和Net 5上进行了测试。


您介意详细说明为什么需要将其转换为 Span 类型吗? - Zhe Chen
@ZheChen 很好的问题,我不确定具体原因。我的猜测是 Span 会在循环期间将数组固定在内存中的特定位置,因此可以进行安全引用。 - Frederic

1

在C#的foreach循环中,是否可以通过引用迭代int数组?

不可以。C#中的foreach循环不允许对其迭代的集合进行更改。它使用一个只读的本地变量,不能用作赋值目标。

但是你可以使用for循环来实现:

var list = new List<MyClass>();

for(var i = 0; i < list.Count; i++)
{
   list[i] = new MyClass();
}

或者使用LINQ:
list = list.Select(e => new MyClass()).ToList(); // note that this will create a copy of list

0

是的,这在与问题中提出的完全相同的语法中是可能的。

根据微软文档:从C# 7.3开始,如果枚举器的Current属性返回一个引用返回值(ref T,其中T是集合元素的类型),则可以使用ref或ref readonly修饰符声明迭代变量。

https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/foreach-in

例子:

int val = 0;
int[] tab = new int[5];

foreach (ref int i in tab) {
    i = val++;
}

foreach (ref readonly var j in tab) {
    Console.WriteLine(j);
}

输出:

0
1
2
3
4

2
你是在什么样的项目中创建了这个功能?我很想使用它,但在.NET Core 3.1类库(C# 8)中,它会抛出编译错误。 - Dan
无法编译。显然,您需要将数组转换为 span 才能使其正常工作。请参见我的答案以获取示例。 - Frederic
@Dan 使用 .NET Framework 4.5 的 Windows Forms 和 WPF。 - Makaveli84

0
不,foreach循环不允许循环变量引用另一个变量。它总是将值从序列中复制到一个新变量中。要做你想做的事情,你需要使用除foreach循环之外的某种结构。虽然从技术上讲,你可以编写自己的ForEach方法,接受一个lambda表达式作为参数,其中参数是数组中项目的引用,但结果可能并不值得。
public delegate void ReferenceAction<T>(ref T param);
public static void ForEach<T>(T[] source, ReferenceAction<T> action)
{
    for (int i = 0; i < source.Length; i++)
        action(ref source[i]);
}

int[] tab = new int[5];
ForEach(tab, (ref int n) => n = 5);

几乎肯定有更好的方法来完成你想做的事情,而不是实际上使用循环变量作为引用。


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