【问题标题】:Why this custom dictionary class is not working - C# 4.0为什么这个自定义字典类不起作用 - C# 4.0
【发布时间】:2012-03-06 09:13:21
【问题描述】:

我正在为我的任务编写一个自定义字典类,但它给出了错误。这堂课有什么问题?谢谢

        public struct MyValue
    {
        public int irValue1;
        public int irValue2;
    }

    public class csCustomDictionary : Dictionary<string, MyValue>
    {
        public void Add(string srKey, int irVal1, int irVal2)
        {
            if (this.ContainsKey(srKey) == true)
            {
                this[srKey].irValue1 = this[srKey].irValue1 + irVal1;
                this[srKey].irValue1 = this[srKey].irValue2 + irVal2;
            }
            else
            {
                MyValue val;
                val.irValue1 = irVal1;
                val.irValue2 = irVal2;
                this.Add(srKey, val);
            }
        }
    }
}

这是错误信息

C# 4.0

修改后的版本是否正确

    public class csMyValue
{
    public int irValue1;
    public int irValue2;
}

public class csCustomDictionary : Dictionary<string, csMyValue>
{
    public void Add(string srKey, int irVal1, int irVal2)
    {
        if (this.ContainsKey(srKey) == true)
        {
            this[srKey].irValue1 = this[srKey].irValue1 + irVal1;
            this[srKey].irValue1 = this[srKey].irValue2 + irVal2;
        }
        else
        {
            csMyValue val = new csMyValue();
            val.irValue1 = irVal1;
            val.irValue2 = irVal2;
            this.Add(srKey, val);
        }
    }
}

【问题讨论】:

  • 什么错误?它在哪里?你有例外吗?它没有按预期执行吗?不要让我们成为侦探。
  • 添加了错误图片。请刷新并重新检查
  • 您知道只需单击错误并按 F1 即可获取此帮助页面吗? Compiler Error CS1612

标签: c# class c#-4.0 dictionary custom-attributes


【解决方案1】:

问题是您在字典中使用struct 作为您的值。

当您编写:this[srKey] 时,您实际上检索了存储为字典值的 结构副本。因此,.irValue1 正在尝试在副本上设置一个字段(该字段很快就会消失)。

如果您将MyValue 更改为一个类,这应该可以。这也更合适,因为您正在创建一个可变类型,而可变结构很少是一个好主意。

话虽如此,您可以通过临时设置字段,然后在字典中设置值来强制它工作:

if (this.ContainsKey(srKey) == true)
{
    MyValue tmp = this[srKey];
    tmp.irValue1 += irVal1;
    tmp.irValue2 += irVal2;
    this[srKey] = tmp;
}

如果您将MyValue 更改为类而不是结构,您可以这样写:

    MyValue tmp = this[srKey];
    tmp.irValue1 += irVal1;
    tmp.irValue2 += irVal2;

由于存储的值将是一个引用,这将进行您希望的更改,而不需要大量的字典查找。

【讨论】:

  • 非常感谢您的回答。我修改了问题并添加了课程版本。那会很好用吗?还是有更好的方法?
  • @MonsterMMORPG 类版本可以工作 - 但请阅读我的上一节;)它显示了使用类的更好版本(获取 tmp,增量),因为它不必进行字典查找4 次,只有一次。
  • 所以我只使用你的版本而不是 if 语句?或者只是替换 if 检查的内部?
  • 并不是说不需要this[srKey] = tmp这一行,因为内存中只有一个对象的副本,所以tmp.irValue1 += irVal1已经改变了字典中的对象。
  • @Diego MyValue 是一个 struct,正如原始问题中所写,这是不正确的。 tmp 是存储在字典中的结构的副本,因此您必须在副本中设置值,然后设置整个结构(将其复制回字典条目)。这就是原始错误的全部原因。如果您注意到,最后我提到使用类时不需要这样做。
【解决方案2】:

我认为这是在说 this[whatever] 不能位于作业的左侧。试试这个:

public class csCustomDictionary : Dictionary<string, MyValue>
{
    public void Add(string srKey, int irVal1, int irVal2)
    {
        if (this.ContainsKey(srKey) == true)
        {
            var myVal = this[srKey];
            myVal.irValue1 = myVal.irValue1 + irVal1;
            myVal.irValue1 = myVal.irValue2 + irVal2;
        }
        else
        {
            MyValue val;
            val.irValue1 = irVal1;
            val.irValue2 = irVal2;
            this.Add(srKey, val);
        }
    }
}

【讨论】:

  • 这将编译,但不会实际更改字典中的值...您的更改使其成为空操作。
  • 但它也揭示了为什么 C#不允许你这样做:)
  • 里德,这绝对不是真的。内存中只有一个对象的副本。
  • @Diego 没有结构。试试看,这行不通。一旦使用此代码添加结构值,您将永远不会更改它。为了使它工作,MyValue 必须是一个类(引用类型),而不是一个结构(值类型),因为值类型具有复制语义。
  • @Diego 在原始帖子中 - 第一行代码包含 public struct MyValue - 这就是这里的全部问题。如果它是一个类,那么 OP 的代码实际上可以在没有编译器投诉的情况下运行。
【解决方案3】:

C# 不允许你这样做,因为 MyValue 是一个结构。

this[...] 方法将返回数据的副本,因此如果您更改字段,它不会做任何事情。

改为类。

如果你真的需要它是一个结构,你可以这样做:

var tmp = this[srKey];
tmp.irValue1 += irVal1;
this[srKey] = tmp;

【讨论】:

  • 非常感谢您的回答。我修改了问题并添加了课程版本。那会很好用吗?还是有更好的方法?
【解决方案4】:

使用索引器时,您实际上得到了MyValue 的副本,因为它是一个结构类型。编译器实际上在很大程度上帮助了您,让您知道代码没有按照您的预期执行。要解决此问题,您需要直接分配一个新值。

var current = this[srKey];
this[srKey] = new MyValue { 
    irValue1 = current.irValue1 + irVal1, 
    irValue2 = current.irValue2 + irVal2 
};

【讨论】:

    【解决方案5】:

    要创建自定义Dictionary,需要继承IDictionary &lt;int, MyValue&gt;并实现接口,Add()、Remove()等

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-10-06
      • 2016-04-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-05
      • 1970-01-01
      相关资源
      最近更新 更多