Issues with LINQ and object references

I'm stuck trying to get something in the following lines to work, here is a complete example of code that can be run inside Visual Studio that demonstrates the script I'm talking about. Everything here works as expected, when I change the player's IsReady value, the lambda attached to the event fires, and if (to) evaluates to true. However, Console.WriteLine never hits because it seems that the IsReady value for the player in the ConcurrentBag is not updated.

class Program { public static ConcurrentBag<Player> Players { get; set; } static void Main(string[] args) { Players = new ConcurrentBag<Player>(); Player player = new Player() { Id = "123" }; Players.Add(player); player.IsReady.ValueChanged += (from, to) => { if (to) { if (Players.All(p => p.IsReady.Value)) { Console.WriteLine("It worked"); } } }; LookupPlayerById("123").IsReady.Value = true; } public static Player LookupPlayerById(string clientId) { var player = Players.FirstOrDefault(x => x.Id == clientId); return player; } } public class Player { public string Id { get; set; } public MonitoredValue<bool> IsReady { get; set; } public Player() { IsReady = new MonitoredValue<bool>(false); } } public class MonitoredValue<T> { public delegate void ValueChangedHandler(T from, T to); public event ValueChangedHandler ValueChanged; private T m_Value; public T Value { get { return m_Value; } set { if (ValueChanged != null) // if invocation list is not empty, fire the event { ValueChanged(m_Value, value); } m_Value = value; } } public MonitoredValue() { } public MonitoredValue(T initialValue) { m_Value = initialValue; } } 
+4
source share
2 answers

The problem is that you first notify your listeners and then actually change the meaning. Change your ownership definition to the code below:

( delegate {} if the default implementation is the default, now I do not need to check the null value before each call)

 public event ValueChangedHandler ValueChanged = delegate {}; public T Value { get { return m_Value; } set { //first change m_Value = value; //now notify ValueChanged(m_Value, value); } } 
+3
source

Since this is a reference type, Player will be referenced by the object returned by FirstOrDefault, unless it is the default, in which case you will not get a match.

Demo example:

  public static void Main() { ConcurrentBag<ClassA> test = new ConcurrentBag<ClassA>(); var hurp = new ClassA(); hurp.number = 3; test.Add(hurp); var derp = test.FirstOrDefault(); derp.number = 4; Console.Write(test.FirstOrDefault().number); Console.WriteLine(derp.number); Console.ReadLine(); } 

Print: 44

0
source

All Articles