Question

I got the following error which I translated from German:

error BC30068: The Expression is a value and cannot be target of an assignment.

I am trying to do the following:

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

Where I have declared Cells as:

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

How can I solve this problem? I do not want Cell to be a Class but instead to be a struct, because otherwise any access would create a new object on the heap. Sure I could cache all created Cell Objects but this could introduce bugs and wastes lots of memory and a new layer of indirection.

Is there a better way to do it?

Was it helpful?

Solution 4

I now solved it by returning a CellCollection from the Cells property which contains an indexer. This way Iam no more getting the error and I just create one single object for all cells.

OTHER TIPS

What's the problem in making it a class?

Also, why don't you just use an indexer instead:

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

that way, you can use it like that:

sheet[column, row] = newValue;

If it is a struct, you're going to have to get the value out, modify it, and pass it back in:

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

But frankly I think your assertion of an object (class) per cell being too expensive is missing the point...

BTW, I would also advise that structs should be immutable whenever possible (with the possible exception of XNA, for specific reasons).

The behavior you are seeing is a consequence of the fact that .net makes no distinction between struct properties and methods which mutate the fields struct itself and those which do not. Ideally, .net languages would forbid the use of any mutating methods and properties on read-only structs, while permitting non-mutating ones. Unfortunately, since .net provides no indication of whether a struct method or property will mutate the underlying struct, today's C# and vb.net simply assume that property setters will affect the underlying struct, and other methods will not. Older C# compilers allow the invocation of all struct member code, including property getters, often with undesired results.

It's too bad that Microsoft decided that structs should be mutated using property setters, rather than specifying that structs which were going to be mutable should either expose fields directly or else be modified using static methods. Had they adopted such an approach on things like Point, the complaints which caused mutable structs to be branded as "evil" would have been averted, and code such as yours would have worked just fine. Oh well, so much for the wonders of useless "encapsulation".

My answer would have been - don't make the Value a property. Make it two methods - GetValue() and SetValue(). This way there are no assignments.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top