无法修改'System.Collections.Concurrent.ConcurrentDictionary的返回值

时间:2014-11-26 22:03:11

标签: c# .net concurrency

我在尝试修改ConcurrentDictionary中的项目时遇到了非常奇怪的错误:

private ConcurrentDictionary<string, Tripple> SeenEnoughDict =   
               new ConcurrentDictionary<string, Tripple>();  
private struct Tripple
{
    public int prev_antenna;
    public int num_of_times_seen;
    public Timer timer;

    // ctor
    public Tripple(int antenna, Timer tm)
    {
        this.prev_antenna = antenna;
        this.num_of_times_seen = 1;
        this.timer = tm;
    }
} 
// several items were added to the dictionary

 Parallel.ForEach(_myReaderTC.Cast<Tag>(), t => {
     // attempting to modify the item  
     // t.ID is string    
     SeenEnoughDict[t.ID].num_of_times_seen = SeenEnoughDict[t.ID].num_of_times_seen + 1; 
}

最后一行抛出错误:

Error 149   Cannot modify the return value of  
'System.Collections.Concurrent.ConcurrentDictionary<string,Tripple>.this[string]'   
because it is not a variable

有关此错误的有趣之处在于http://pastebin.com/0cQJMcUD可以正常运行。 最近,我已经将我的解决方案从2010年转换到2013年。2010年,我使用了从.NET 4反向移植到3.5的Concurrency集合(我从NuGet获得了它)。

1 个答案:

答案 0 :(得分:2)

这是因为您的类型是struct。一般来说,除非您知道具有创建值类型(struct)的特定原因,否则您应该真正创建class。如果您要修改它的某些内容(即您创建的内容并不代表谨慎的“价值”而改变某些内容并不会使其本身成为其他东西),那么您应该肯定使用class。在解决您的问题方面,只需将struct替换为class即可。

但是,我还建议公开属性而不是字段。 .NET语言中的一般习惯是使用private支持字段,并在必要时通过使用属性将它们暴露在声明类之外。所以不要这样:

public class Foo
{
    public int MyValue;
}

你这样做:

public class Foo
{
    private int myValue;

    public int MyValue
    {
        get { return myValue; }
        set { myValue = value; }
    }
}

我意识到这有点罗嗦,但对于简单的属性(简单的get / set操作除了设置所需字段的值之外没有任何东西),你可以使用“自动属性”

public class Foo
{
    public int MyValue { get; set; }
}

对于简单的get / set操作,属性语法不再冗长,但仍然可以灵活地分离属性为您提供的关注点。

最后我建议采用PascalCase名称,因为这是你在大多数.NET语言中都能找到的。

完成所有这些更改后,您的课程将如下所示:

private class Tripple
{
    public int PrevAntenna { get; set; }
    public int NumOfTimesSeen { get; set; }
    public Timer Timer { get; set; }

    // ctor
    public Tripple(int antenna, Timer tm)
    {
        this.PrevAntenna = antenna;
        this.NumOfTimesSeen = 1;
        this.Timer = tm;
    }
} 

我觉得你的班级可以使用一个更有意义的名字(除非“Tripple”在你的工作中有一些行业特定的含义,我只是不知道),但希望这足以提供帮助