我在尝试修改foreach中的事务列表时遇到问题。我创建了传递给我的方法的列表的副本,使其只读,但当我尝试更改任何列表中的值时,它会更改其中的所有值。某种类型的内存链接?我不确定如何解决这个问题。
我的程序首先声明一个名为Transaction的类(这是一个具有Name,Value,Formatting的泛型类),然后我有subClasses:Transaction。我创建了一个TransList(来自公共类TransList:IEnumerable),它有一个每个subClass的对象实例。因此,TransList将包含名为TranID,Amount,OrderID,Time,CardType,Comment1,Comment2的类。这些子类的每个值可以是字符串,十进制,DateTime。之后创建一个TransParts列表,然后将其放入一个名为processTrans的更大列表中。
因此,Comment2是具有付款引号的元素,如果有多个号码,我想将其分成多个TransList,将这些新的TransLists添加到processTrans并删除未分离的号码。从下面的代码中,尝试了每个策略后,运行时修改不仅发生在预期的processTrans,还发生在tempProcessTrans,addOn,tran,tranPart。
如果传入方法的processTrans在调试器本地中如下所示
processTrans [0] _Items TranID.Value = SD234DF和Comment2 = adf; wer;
那么输出应该是
processTrans [0] _Items TranID.Value = SD234DF-1和Comment2.Value = adf
processTrans [1] _Items TranID.Value = SD234DF-2和Comment2.Value = wer
我目前得到了
processTrans [0] _Items TranID.Value = SD234DF-1-2和Comment2.Value = wer
processTrans [1] _Items TranID.Value = SD234DF-1-2和Comment2.Value = wer
public static List<TransList> SeperateMultiCitations(List<TransList> processTrans) //change TransList seperating Multiple Citations
{
List<int> indexes=new List<int>();
IList<TransList> tempProcessTrans = processTrans.AsReadOnly(); //this didn't help
List<TransList> addOn= new List<TransList>(); //copy list didn't stop from changes to occur in processTrans at same time
foreach (TransList tran in tempProcessTrans.ToList())
{
TransList copyTransList = tran;
foreach (Transaction tranPart in tran.OfType<Comment2>())
{
if (new Regex(";.+;").IsMatch((string)tranPart.Value, 0))
{
string[] citations = Regex.Split((string)tranPart.Value, ";").Where(s => s != String.Empty).ToArray();
int citNumb = 1;
indexes.Add(tempProcessTrans.IndexOf(tran));
foreach (string singleCitation in citations)
{
addOn.Add(ChangeTrans(tran, singleCitation, citNumb++)); when this line runs changes occur to all lists as well as trans, tranPart
}
break;
}
}
}
foreach (int index in indexes.OrderByDescending(x => x))
{
processTrans.RemoveAt(index);
}
processTrans.AddRange(addOn);
return processTrans;
}
public static TransList ChangeTrans(TransList copyTransList, string singleCitation, int citNumb) //add ConFee
{
foreach (Transaction temp in copyTransList.OfType<TranID>())
{
temp.Value += "-" + citNumb;
}
foreach(Transaction temp in copyTransList.OfType<Comment2>())
{
temp.Value = singleCitation;
}
foreach (Transaction temp in copyTransList.OfType<Amount>())
{
//temp.Value = DboGrab(temp);
//temp.Value = amount;
}
return copyTransList;
}
public class Transaction : TranInterface
{
public string Name;
public object Value;
public string Formating;
public Transaction(string name, object value, string formating)
{
Name = name;
Value = value;
Formating = formating;
}
}
class TranID : Transaction
{
public TranID(string Name, string Value, string Formating) : base("Transaction ID", Value, "@") { }
}
public class TransList : IEnumerable<Transaction> //not to add all the lengthy parts here but this just allows for adding the parts and iterating through them in the foreach statements
{}
答案 0 :(得分:3)
您所看到的行为是reference types
的固有特征。当您调用ChangeTrans()
方法时,该方法返回的引用与您传入的引用完全相同,即原始值tran
。在内部循环中,tran
的值永远不会改变,因此在循环的每次迭代中,您反复修改同一个对象,并在每次迭代时将其添加到addOn
列表中。
这有两个不良影响:
addOn
列表中的每个元素之间没有区别。它们都是相同的,引用相同的单个对象。addOn
列表中任何单个元素的任何修改,或者通过对该单个对象的原始引用的任何修改,都可以通过对该同一个对象的每个其他引用来显示。即通过列表中的所有其他元素,甚至是tran
变量中的原始引用(当然还有copyTranList
变量,该变量已分配给tran
的值)。 如果没有更完整的代码示例,就无法确定最佳解决方案是什么。但是,一个天真的解决方案是简单地更改您的ChangeTrans()
方法,以便它负责制作新副本:
public static TransList ChangeTrans(
TransList copyTransList, string singleCitation, int citNumb) //add ConFee
{
TransList newTransList = new TransList();
foreach (Transaction temp in copyTransList.OfType<TranID>())
{
Transaction newTransaction = new TranID();
newTransaction.Value = temp.Value + "-" + citNumb;
newTransList.Add(newTransaction);
}
foreach(Transaction temp in copyTransList.OfType<Comment2>())
{
Transaction newTransaction = new Comment2();
newTransaction.Value = singleCitation;
newTransList.Add(newTransaction);
}
return newTransList;
}
注意:我不知道上面是否真的会编译,或者它是否实际上复制了所需的所有值。我重申:既然你没有展示TransList
或Transaction
数据结构,就不可能知道它们中的所有数据都需要复制,也不知道复制这些数据的最佳方法是什么。< / p>
那说,在上面的例子中注意到这个版本的方法:
TransList
对象的全新实例,将引用存储在newTransList
中。Transaction
值,它会创建一个全新的Transaction
实例(使用适当的类型),并为分配实例的Value
属性修改后的值。Transaction
个对象,它会将对象添加到TransList
变量引用的新创建的newTransList
对象中。TransList
对象,而不是传递给方法的对象。据推测,您知道向Transaction
对象添加TransList
元素的正确方法,以及Transaction
对象中是否还有其他成员需要复制。以上只是您可以在何处以及如何修改代码的基本说明,以便您执行所需的“深层复制”以避免您所描述的问题。