When adding to a list, if I add the property of a class instance, is it set to a reference of the property's value or a reference to the property?
Example:
If I have:
class A {
public Action<Guid> SomeDelegate { get; set; }
}
And in a different class I create an instance of class A, ie:
class B {
public B() {
a = new A();
a.SomeDelegate = someFunction;
List<Action<Guid>> myList = new List<Action<Gui开发者_如何学编程d>>;
myList.Add(a.SomeDelegate);
a.SomeDelegate = anotherFunction;
}
}
What will be in myList
? A reference to anotherFunction
or a reference to someFunction
?
If it is a reference to someFunction
, how would I go about making it a reference to anotherFunction
?
Thanks!
The single item in your list will be a reference to someFunction
.
Think of like this:
You have an instance of A
. Now A
has a property called SomeDelegate
. You have a references someFunction
and anotherFunction
to delegates that I will also call someFunction
and anotherFunction
respectively in the pictures below. So the picture is this:
a local to B constructor
---------------
| |
|SomeDelegate-----------> someFunction
| | anotherFunction
---------------
Now you add a.SomeDelegate
to myList
. So the picture is this:
a local to B constructor
---------------
| |
|SomeDelegate-----------> someFunction <-------myList[0]
| | anotherFunction
---------------
Now you come along and change SomeDelegate
to refer to anotherFunction
. Now the picture is this:
a local to B constructor
---------------
| |
|SomeDelegate-----| someFunction <-------myList[0]
| | |-----> anotherFunction
---------------
This should make it clear that myList[0]
still refers to someFunction
and why.
Now, if you want myList
to see the changes, the best easiest way is to make it a list of A
.
A a = new A();
a.SomeDelegate = someFunction;
List<A> myList = new List<A>();
myList.Add(a);
a.SomeDelegate = anotherFunction;
Now it will be the case that myList[0].SomeDelegate
refers to anotherFunction
. You can easily extract the actions like so:
var actions = myList.Select(x => x.SomeDelegate).ToList();
I believe the List would continue to hold a reference to a delegate instance pointing to SomeFunction.
The low-tech solution to achieving what you want to achieve would be to wrap the delegate inside another object. Add this object to the list; you are then free to mutate the wrapper object, change its property to the new value.
At the point where you consume the delegates in the list, instead of directly invoking the delegate, use wrapperInstance.Delegate(params)
Update: I think my response wasn't clear from Jason's comment.
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());
}
}
A list of a class type will hold references to outside objects. Anything that happens to an object to which the list happens to hold a reference, will happen to the object referred to by the list (since the object to which the list holds a reference is the object referred to by the list).
Note that lists of structure types behave differently. If a list holds a structure type, the only way to make any change to a structure therein is to create a new instance of the structure, reflecting the desired changes, and store it to the list. For example:
List<Point> myList = ...; // Initialize it somehow Point tempPt = myList[4]; tempPt.X = 19; myList[4] = tempPt;
While it would be possible to design a generic container-of-struct which would expose some other means of acting on structs contained therein (e.g.
myContainer.ActOnItem(4, (ref Point pt) => {pt.X = 19;});
none of the container types built into .net provide any such functionality.
精彩评论