创建对对象的原始引用的抓取包(集合)
本文关键字:集合 抓取 引用 对象 原始 创建 | 更新日期: 2023-09-27 18:22:04
我正在寻找一种类型/方法的集合,在这种集合中,我可以将一个对象添加到一组对象中,然后分别更改该对象的属性,并将这些更改反映在集合中的对象中。
我听说List<T>通过引用添加值,所以我认为引用将指向同一个对象。换句话说,我假设:
List<string> valuesList = new List<string>();
string initialValue = "Alpha";
valuesList.Add(initialValue);
initialValue = "Bravo";
bool incorrectAssumption = (valuesList[0] == "Bravo");
我曾希望"valuesList"会包含新的值"Bravo"。尝试了一下,我意识到List复制了引用,它没有吸收它,所以valueList仍然只有"Alpha"值。有什么方法可以将集合用作它们所包含的合法少数对象吗?
如果这有助于了解实际的业务需求。。。。
List<BaseWidget> widgets = new List<BaseWidget>();
DerivedWidget specialWidget = new DerivedWidget();
DerivedWidget extraSpecialWidget = new DerivedWidget();
widgets.Add(specialWidget);
widgets.Add(extraSpecialWidget);
specialWidget.Run();
extraSpecialWidget.Run();
if (!widgets.Any(x => x.RunSuccessfully)) return false;
(其中Run()方法设置RunSuccessfully属性,我希望它反映在"widgets"列表中。)
=============================================
更新
正如答案和评论中所指出的,业务需求模型和试运行示例之间存在一些差异。我将把人生的教训浓缩为:似乎List<objects>
有他们的变化被跟踪,而List<values>
没有。
好吧。你似乎不明白到底发生了什么。这是一篇关于.net类型内部构件的好文章。
很快,在您的字符串示例中会发生什么:
- 您创建列表
- 您可以创建字符串类型的变量initialValue。此变量的值存储在特殊的局部变量容器中。因为字符串是引用类型,所以在局部变量的容器中,它作为指向对象的指针包含
- 创建新字符串"Alpha",将其存储在堆中,并将指针(指向该字符串)分配给本地变量
- 然后将对象添加到列表中。在您的列表中,此对象存储为指向某个位置的指针
- 然后通过将局部变量"initialValue"分配给指向另一个字符串的指针来更改其内容。所以,现在在局部变量initialValue中是一个指针,在列表中是另一个指针
那么,解决方案呢?
-
把你的绳子绕到另一个班上。像这样:
class Wrapper<T> { public T Content {get;set;} public Wrapper(T content) { Content = content; } }
用法:
void Main() { var valuesList = new List<Wrapper<string>>(); var initialValue = new Wrapper<string>("Alpha"); valuesList.Add(initialValue); initialValue.Content = "Bravo"; Console.WriteLine(valuesList[0].Content); }
语法有点难看。
-
使用clojures:
void Main() { List<Func<string>> valuesList = new List<Func<string>>(); string initialValue = "Alpha"; valuesList.Add(() => initialValue); initialValue = "Bravo"; Console.WriteLine(valuesList[0]() == "Bravo"); }
所有对非值类型的引用都将通过引用传递,无论是否为List<T>
然而,字符串是一种值类型,并且总是通过值传递。它们也是不可变的,所以每当您更改一个时,实际上就是在创建一个新的String。
对于您的示例,您可以创建一个包含字符串的包装器类型,并将其存储在List<T>
中。
您的实际业务案例似乎应该正常工作,除非它们被声明为structs。