4

次の行に沿って何かを機能させようとして立ち往生しています。これは、私が話しているシナリオを示す Visual Studio 内で実行できる完全なコード例です。プレイヤーの IsReady 値を変更すると、イベントに関連付けられたラムダが起動され、if (to) が true と評価されます。ただし、ConcurrentBag 内のプレーヤーの IsReady の値が更新されていないように見えるため、Console.WriteLine はヒットしません。

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

2 に答える 2

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

    }
}
于 2013-03-31T20:59:06.757 に答える
0

これは参照型であるため、一致が得られなかった Default でない限り、Player は 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

于 2013-03-31T20:58:59.090 に答える