Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/265.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# LINQ和对象引用的问题_C#_Linq_Collections - Fatal编程技术网

C# LINQ和对象引用的问题

C# LINQ和对象引用的问题,c#,linq,collections,C#,Linq,Collections,我一直在努力让下面的内容起作用,下面是一个完整的代码示例,可以在VisualStudio内部运行,它演示了我正在讨论的场景。这里的一切都按预期工作,当我更改播放器的IsReady值时,将触发附加到事件的lambda,如果(to)计算为true。但是,Console.WriteLine从未被命中,因为ConcurrentBag中的播放器的IsReady值似乎没有更新 class Program { public static ConcurrentBag<Player> Play

我一直在努力让下面的内容起作用,下面是一个完整的代码示例,可以在VisualStudio内部运行,它演示了我正在讨论的场景。这里的一切都按预期工作,当我更改播放器的IsReady值时,将触发附加到事件的lambda,如果(to)计算为true。但是,Console.WriteLine从未被命中,因为ConcurrentBag中的播放器的IsReady值似乎没有更新

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;
    }
}
类程序
{
公共静态ConcurrentBag播放器{get;set;}
静态void Main(字符串[]参数)
{
玩家=新的ConcurrentBag();
Player Player=new Player(){Id=“123”};
Players.Add(player);
player.IsReady.ValueChanged+=(从,到)=>
{
若(至)
{
if(Players.All(p=>p.IsReady.Value))
{
Console.WriteLine(“它起作用”);
}
}
};
LookupPlayerById(“123”).IsReady.Value=true;
}
公共静态播放器LookupPlayerById(字符串clientId)
{
var player=Players.FirstOrDefault(x=>x.Id==clientId);
返回球员;
}
}
公开课选手
{
公共字符串Id{get;set;}
public MonitoredValue是ready{get;set;}
公共玩家()
{
IsReady=新的监控值(false);
}
}
公共类监视值
{
公共代表无效值更改句柄(T from,T to);
公共事件值更改处理程序值更改;
私人T m_值;
公共价值
{
获取{返回m_值;}
设置
{
if(ValueChanged!=null)//如果调用列表不为空,则触发事件
{
值已更改(m_值、值);
}
m_值=值;
}
}
public MonitoredValue(){}
公共监视器默认值(T初始值)
{
m_值=初始值;
}
}

由于它是一种引用类型,因此FirstOrDefault返回的对象将引用Player,除非它是默认值,在这种情况下,您没有获得匹配项

举例说明:

    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();
    }
publicstaticvoidmain()
{
ConcurrentBag测试=新ConcurrentBag();
var hurp=新的ClassA();
hurp.number=3;
测试。添加(hurp);
var derp=test.FirstOrDefault();
derp.number=4;
Console.Write(test.FirstOrDefault().number);
控制台写入线(derp.number);
Console.ReadLine();
}
印刷品:
44

问题是您首先通知您的侦听器,然后实际更改值。 将属性定义更改为下面给出的代码:

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


Player
结构
?然后将
引用
返回给Player对象。更改其状态将影响同一对象,如果您知道使用C#和LINQ执行此操作的方法,请共享
ConcurrentBag
中的链接。这是我尝试做的第一件事,但这似乎是技术的局限性?我一定要用光吗?我的印象是,返回FirstOrDefault()将阻止您使用引用如果(Players.All(p=>p.IsReady.Value))类的“默认”为
null
,那么他的代码将在该场景中爆炸,我刚刚运行了你的代码,发现它的行为和预期的一样。也许我丢失的MonitoredValue出现了问题,请查看我更新的代码示例,以查看一个完整且包含的解决方案,该解决方案可以重新创建problem@JesseCarter解决了你的问题。对我来说,它打印了“它成功了”哦,天哪,我真不敢相信我错过了。。。非常感谢你的帮助,我想弄清楚我错过了什么,真是疯了。@JesseCarter没关系,我们都会犯这些错误。我发现单元测试在减少此类bug的数量方面帮了我很大的忙。
public event ValueChangedHandler ValueChanged = delegate {};

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

        //now notify
        ValueChanged(m_Value, value);

    }
}