2013-03-31 35 views
4

我被困在试图让下面几行工作的东西,这里是一个完整的代码示例,可以在Visual Studio中运行,演示我正在谈论的场景。当我改变播放器的IsReady值时,这里的一切都按预期工作,附加到事件的lambda被触发,并且(如果)评估为true。然而,Console.WriteLine从来没有命中,因为看起来ConcurrentBag中播放器的IsReady值没有更新。与LINQ和对象引用相关的问题

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; 
    } 
} 
+1

'Player'是'class'或一个'struct'? –

+0

玩家是一个类 –

+2

然后你返回一个'参考'到Player对象。改变它的状态将影响同一个对象,从'ConcurrentBag '被存储的链接 –

回答

3

的问题是,你先通知你的听众,然后真正改变值。 更改属性定义如下代码:

delegate {}如果违约事件的实现,现在我不需要每次调用前检查null)

public event ValueChangedHandler ValueChanged = delegate {}; 

public T Value 
{ 
    get { return m_Value; } 
    set 
    { 
     //first change 
     m_Value = value; 

     //now notify 
     ValueChanged(m_Value, value); 

    } 
} 
+0

嗯,我刚刚运行了您的代码,发现它的行为与预期相同。可能是我正在丢失的MonitoredValue发生了什么 –

+0

请查看我更新的代码示例以查看重新创建问题的完整解决方案 –

+0

@JesseCarter解决了您的问题。对我来说''它工作'' –

0

既然是引用类型,玩家将通过FirstOrDefault返回,对象引用,除非它是默认的,这种情况下,你没有得到匹配。

例子来说明:

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

打印: 44

+0

对于类为“null”的“默认”,所以他的代码在这种情况下会炸毁,就像你的代码一样。 –

+0

确实,但我假设他确实在他的收藏中拥有实体。 –