创建对对象的原始引用的抓取包(集合)

本文关键字:集合 抓取 引用 对象 原始 创建 | 更新日期: 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类型内部构件的好文章。

很快,在您的字符串示例中会发生什么:

  1. 您创建列表
  2. 您可以创建字符串类型的变量initialValue。此变量的值存储在特殊的局部变量容器中。因为字符串是引用类型,所以在局部变量的容器中,它作为指向对象的指针包含
  3. 创建新字符串"Alpha",将其存储在堆中,并将指针(指向该字符串)分配给本地变量
  4. 然后将对象添加到列表中。在您的列表中,此对象存储为指向某个位置的指针
  5. 然后通过将局部变量"initialValue"分配给指向另一个字符串的指针来更改其内容。所以,现在在局部变量initialValue中是一个指针,在列表中是另一个指针

那么,解决方案呢?

  1. 把你的绳子绕到另一个班上。像这样:

    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);
    }
    

    语法有点难看。

  2. 使用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。