按值传递struct

Man*_*eld 1 .net c# structure pass-by-reference pass-by-value

鉴于以下代码,我很想知道如何避免以下异常

System.InvalidOperationException was unhandled
Message=Collection was modified; enumeration operation may not execute.
Source=mscorlib
StackTrace:
   at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
   at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
   at System.Collections.Generic.List`1.Enumerator.MoveNext()
   at PBV.Program.Main(String[] args) in C:\Documents and Settings\tmohojft\Local Settings\Application Data\Temporary Projects\PBV\Program.cs:line 39
   at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
   at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
   at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()
InnerException: 
Run Code Online (Sandbox Code Playgroud)

码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PBV
{
class Program
{
    struct structItem
    {
        public int y { get; set; }
        public int z { get; set; }
    }

    struct testStruct
    {
        public int x { get; set; }
        public List<structItem> items { get; set; }
    }

    static void Main(string[] args)
    {
        testStruct a = new testStruct();
        structItem b = new structItem();

        for (byte i = 0; i <= 10; i++) {
            b.y = i;
            b.z = i * 2;
            a.items = new List<structItem>();
            a.items.Add(b);
        }

        testStruct c = new testStruct();
        c = a;

        int counter = 0;

        //exception thrown on line below
        foreach (var item in a.items) {
            structItem d = item;
            d.z = 3;

            c.items[counter] = d;
            counter++;
        }

        a = c;
    }
}
}
Run Code Online (Sandbox Code Playgroud)

我原本试图简单地将以下内容放在第二个foreach中:

item.z = 3;
Run Code Online (Sandbox Code Playgroud)

但是这导致了以下错误:

Cannot modify members of "item" because it is a "foreach iteration" 
Run Code Online (Sandbox Code Playgroud)

我试图创建一个临时对象,以便能够修改foreach中的struct数据,但我收到了上面的异常.我最好的猜测是因为我的临时结构正在保存对原始结构的引用而不是值本身 - 这导致我的原始结构在我的临时结构时更新.

所以我的问题是: 如何通过值而不是引用传递此结构?或者是否有一种完全不同的方式来解决这个问题?

在此先感谢您的帮助.

编辑:谢谢你的所有答案.我知道列表是一个引用类型,但这是否使得无法通过值而不是引用传递?

Ste*_*art 5

我对你的示例代码试图做的事情感到有点困惑,但我想也许你的困惑可能部分是当你设置时c = a,你希望它能够复制一份列表.它不是.虽然结构本身是值类型,但它包含的items属性却不是.List <>是引用类型,因此在设置时c = a,它会复制items对c的引用.因此,当您进入循环时,a和c都包含对同一列表对象的引用.因此,当您通过它枚举时修改列表时,它将始终失败.

避免这种情况的一种简单方法是遍历列表的静态副本:

foreach (var item in a.items.ToArray())
Run Code Online (Sandbox Code Playgroud)

  • +1,但OP是一个很大的禁忌来修改你枚举的可枚举的WHILE.考虑为您想要做的事情选择不同的策略. (2认同)