是否有列表<>存储对属性或实例的引用?

时间:2009-12-31 04:12:40

标签: c# .net list reference

当添加到列表时,如果我添加了类实例的属性,它是否设置为属性值的引用或对属性的引用?

示例:

如果我有:

class A {
     public Action<Guid> SomeDelegate { get; set; }
}

在另一个类中,我创建了一个A类实例,即:

class B {
     public B() {
          a = new A();
          a.SomeDelegate = someFunction;
          List<Action<Guid>> myList = new List<Action<Guid>>;
          myList.Add(a.SomeDelegate);
          a.SomeDelegate = anotherFunction;
      }
}

myList会有什么?对anotherFunction的引用或对someFunction的引用?

如果它是对someFunction的引用,我该如何将其作为anotherFunction的引用?

谢谢!

3 个答案:

答案 0 :(得分:4)

列表中的单个项目将引用someFunction

想到这样:

您有一个A的实例。现在A有一个名为SomeDelegate的属性。您有代表someFunctionanotherFunction,我也会在下面的图片中分别致电someFunctionanotherFunction。所以图片就是这样:

a local to B constructor
---------------
|             |
|SomeDelegate-----------> someFunction
|             |           anotherFunction
---------------

现在您将a.SomeDelegate添加到myList。所以图片就是这样:

a local to B constructor
---------------
|             |
|SomeDelegate-----------> someFunction <-------myList[0]
|             |           anotherFunction
---------------

现在你来了,改变SomeDelegate来引用anotherFunction。现在的情况如下:

a local to B constructor
---------------
|             |
|SomeDelegate-----|       someFunction <-------myList[0]
|             |   |-----> anotherFunction
---------------

这应该清楚表明myList[0]仍然引用someFunction以及为什么。

现在,如果您希望myList看到更改,最简单的方法是将其列为A

 A a = new A();
 a.SomeDelegate = someFunction;
 List<A> myList = new List<A>();
 myList.Add(a);
 a.SomeDelegate = anotherFunction;

现在myList[0].SomeDelegate引用anotherFunction的情况就是这样。您可以轻松地提取这样的操作:

 var actions = myList.Select(x => x.SomeDelegate).ToList();

答案 1 :(得分:1)

我相信List会继续持有对指向SomeFunction的委托实例的引用。

实现您想要实现的目标的低技术解决方案是将委托包装在另一个对象中。将此对象添加到列表中;然后,您可以自由地改变包装器对象,将其属性更改为新值 在您使用列表中的委托时,不要直接调用委托,而是使用wrapperInstance.Delegate(params)

更新:我认为我的回答并不清楚杰森的评论。

class B
    {
        List<A> myList;
        public B() {
          var a = new A();
          a.SomeDelegate = ( x => Console.WriteLine("SomeFunction " + x) );
          myList = new List<A>();
          myList.Add(a);               // add wrapper object instead of delegate to list
            SerialInvokeDelegates();   // will invoke SomeFunction

          a.SomeDelegate = (x => Console.WriteLine("AnotherFunction " + x));
            SerialInvokeDelegates();   // will invoke AnotherFunction
        }

        private void SerialInvokeDelegates()
        {
            Console.WriteLine("Invoking all delegates in B's List");
            foreach (var a in myList)
                a.SomeDelegate(Guid.NewGuid());
        }
    }

答案 2 :(得分:1)

类类型列表将保存对外部对象的引用。发生在列表恰好包含引用的对象上的任何事件都会发生在列表引用的对象上(因为列表保存引用的对象是列表引用的对象)。

请注意,结构类型列表的行为有所不同。如果列表包含结构类型,则对其中的结构进行任何更改的唯一方法是创建结构的新实例,反映所需的更改,并将其存储到列表中。例如:

  List<Point> myList = ...; // Initialize it somehow
  Point tempPt = myList[4];
  tempPt.X = 19;
  myList[4] = tempPt;

虽然有可能设计一个通用的容器结构,它会暴露一些其他作用于其中的结构的方法(例如

  myContainer.ActOnItem(4, (ref Point pt) => {pt.X = 19;});

.net中内置的任何容器类型都不提供任何此类功能。