我正在寻找一种类型/集合方法,我可以将对象添加到一组对象中,然后分别更改该对象的属性,并将这些更改反映在集合中的对象中。
我听说过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>
则没有。
答案 0 :(得分:1)
好。看来你真的不明白发生了什么。这是关于.net type internals的精彩文章。
很快,您的示例中包含字符串会发生什么:
那么,解决方案呢?
将您的字符串换行到另一个类。像这样:
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");
}
答案 1 :(得分:0)
所有对非值类型的引用都将通过引用传递,List<T>
或不传递。 String是一种值类型,但始终按值传递。它们也是不可变的,所以每当你改变它时,你实际上都在创建一个新的String。
对于您的示例,您可以创建包含字符串的包装类型,并将其存储在List<T>
中。
您的实际业务案例似乎应该正常运行,除非它们被声明为结构。