Ошибка компиляции при присвоении значения struct в словаре - PullRequest
1 голос
/ 16 сентября 2011

люди, Я получил ошибку компиляции («Невозможно изменить возвращаемое значение словаря, потому что это не переменная») в следующем коде:

public class BaseForm : Form
{

    protected void StoreGridViewPosition(DataGridView grid)
    {

        if (grids.ContainsKey(grid))
        {
            grids[grid].RowIndex = grid.CurrentCell.RowIndex;
            grids[grid].ColumnIndex = grid.CurrentCell.ColumnIndex;
        }

        Cell s = new Cell();
        s.RowIndex = 213;
    }

    protected void LoadGridViewPosition(DataGridView grid)
    {
    }

    private Dictionary<DataGridView, Cell> grids = new Dictionary<DataGridView, Cell>();

    private struct Cell
    {
        public int RowIndex;
        public int ColumnIndex;
    }
}

Но если я заменю struct (Cell) классом, то она работает нормально. Почему это происходит?

Ответы [ 3 ]

6 голосов
/ 16 сентября 2011

Это не сработает, как вы ожидаете. Когда вы звоните:

grids[grid].

A copy структуры возвращается из индексатора, а не как ссылка. Итак, когда вы установите в него:

grids[grid].RowIndex = grid.CurrentCell.RowIndex;

Вы фактически настраиваете копию структуры. Затем эта копия немедленно сбрасывается. Все это связано с семантикой структур тип значения .

Все, что вы можете сделать, если вы используете структуру, это установить совершенно новую структуру в ячейку:

grids[grid] = new Cell { RowIndex = 3, ColumnIndex = 1 };

Или вытащите копию старого и установите ее обратно (игнорируя на мгновение, что структуры действительно всегда должны быть сделаны неизменными :-):

var cell = grids[grid];
cell.RowIndex = 3;
grids[grid] = cell;

Изменение определения класса означает, что индексатор возвращает ссылку на этот класс, которую вы можете изменить, так как ваша ссылка и ссылка в словаре указывают на один и тот же базовый объект.

Компилятор говорит (не так много слов), что вы непреднамеренно пытаетесь изменить копию того, что, по вашему мнению, вы меняете. Вы можете легко совершить ту же ошибку, если представите структуру как свойство класса и попытаетесь изменить члены структуры следующим образом:

myClass.MyPointStruct.X = 2;

(Это похоже на то, что по крайней мере в новом компиляторе появляется то же самое сообщение об ошибке, я мог бы поклясться в одном месте, которое он использовал, чтобы позволить вам сделать это ...)

Или, если вы приведете структуру к интерфейсу, бокс будет упакован в копию.

Этот вопрос очень похож:

Изменить переменную Struct в словаре

1 голос
/ 16 сентября 2011

Когда ваша StoreGridViewPosition вызывает вашу ячейку, вы получаете копию структуры внутри. Ваш звонок обновляет значение, а затем выбрасывает его (т. Е. Ничего полезного).

0 голосов
/ 16 сентября 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...