Почему этот пользовательский класс словаря не работает - C # 4.0 - PullRequest
2 голосов
/ 15 февраля 2012

Я пишу пользовательский класс словаря для своей задачи, но он дает ошибку.В чем проблема в этом классе?Спасибо

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

это сообщение об ошибке

enter image description here

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

Ответы [ 5 ]

3 голосов
/ 15 февраля 2012

Проблема в том, что вы используете 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;

Так как сохраненное значение будет ссылкой, это изменит то, что вы хотите, не требуя большого количества словарных поисков.

1 голос
/ 15 февраля 2012

При использовании индексатора вы фактически получаете копию вашего MyValue, поскольку это структурный тип.Компилятор на самом деле сильно помогает вам, давая понять, что код не выполняет то, что вы ожидаете.Чтобы решить эту проблему, вам нужно напрямую назначить новое значение.

var current = this[srKey];
this[srKey] = new MyValue { 
    irValue1 = current.irValue1 + irVal1, 
    irValue2 = current.irValue2 + irVal2 
};
1 голос
/ 15 февраля 2012

C # не позволит вам сделать это, потому что MyValue является структурой.

Метод this[...] вернет копию данных, поэтому, если вы измените поле, он ничего не сделает.

Вместо этого измените его на класс.

Если вам действительно нужно, чтобы это была структура, вы можете сделать это:

var tmp = this[srKey];
tmp.irValue1 += irVal1;
this[srKey] = tmp;
1 голос
/ 15 февраля 2012

Я думаю, он говорит, что 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);
        }
    }
}
0 голосов
/ 15 февраля 2012

Чтобы создать пользовательский словарь, вам нужно наследовать от IDictionary <int, MyValue> и реализовать интерфейс Add (), Remove () и т. Д.

...