Невозможно присвоить свойство структуры, возвращаемой методом - PullRequest
4 голосов
/ 25 февраля 2010

Я получил следующую ошибку, которую я перевел с немецкого:

ошибка BC30068: выражение является значением и не может быть целью назначения.

Я пытаюсь сделать следующее:

sheet.Cells(row, col).Value = newVal ' this is VB

Где я объявил Клетки как:

public Cell Cells(int x, int y) // this is C#
{
    return new Cell(this, x, y);
}

public struct Cell
{
    Worksheet ws;
    int x;
    int y;

    public Cell(Worksheet ws, int x, int y)
    {
        this.ws = ws;
        this.x = x;
        this.y = y;
    }

    public object Value
    {
        get { return ws.GetCellValue(x, y); }
        set { ws.SetCellValue(x, y, value); }
    }
}

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

Есть ли лучший способ сделать это?

Ответы [ 5 ]

1 голос
/ 22 января 2011

Поведение, которое вы видите, является следствием того факта, что .net не делает различий между свойствами структуры и методами, которые изменяют поля самой структуры, и теми, которые этого не делают. В идеале языки .net запрещали бы использование любых изменяющих методов и свойств в структурах только для чтения, в то же время разрешая использование неизменяемых структур. К сожалению, поскольку .net не дает указаний на то, будет ли метод или свойство структуры изменять базовую структуру, современные C # и vb.net просто предполагают, что установщики свойств будут влиять на базовую структуру, а другие методы этого не сделают. Старые компиляторы C # допускают вызов всего кода члена структуры, включая средства получения свойств, часто с нежелательными результатами.

Очень жаль, что Microsoft решила, что структуры должны быть изменены с помощью установщиков свойств, а не указывать, что структуры, которые должны были быть изменяемыми, должны либо открывать поля напрямую, либо изменяться статическими методами. Если бы они применили такой подход к таким вещам, как Point, жалобы, которые приводили к тому, что изменяемые структуры назывались «злыми», были бы предотвращены, и такой код, как ваш, работал бы просто отлично. Ну что ж, так много за чудеса бесполезной «инкапсуляции».

1 голос
/ 25 февраля 2010

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

Cell cell = sheet.Cells(row, col);
cell.Value = newVal;
sheet.Cells(row, col) = cell; // assuming this has a setter

Но, честно говоря, я думаю, что ваше утверждение о том, что объект (класс) на ячейку слишком дорогой, не имеет смысла ...

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

1 голос
/ 25 февраля 2010

В чем проблема сделать его классом?

Кроме того, почему бы вам не использовать вместо этого индексатор:

public object this[int column, int row] {
    get { return this.GetCellValue(column, row); }
    set { this.SetCellValue(column, row, value); }
}

Таким образом, вы можете использовать его так:

sheet[column, row] = newValue;
0 голосов
/ 01 марта 2010

Мой ответ был бы - не делайте Value свойством. Сделать это двумя способами - GetValue() и SetValue(). Таким образом, нет никаких назначений.

0 голосов
/ 01 марта 2010

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

...