4

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?

2
  • Duplicate: stackoverflow.com/questions/2082900/c-getter-setter-problem To summarize: there's not much you can do. Either you need to instantiate a new struct with the new values and assign it to the property or create accessors for each field of the struct in the parent class and alter them individually. Commented Feb 25, 2010 at 12:04
  • Interesting question and not a duplicate IMHO. Cell may look like a mutable struct to the compiler, while in reality it isn't (assuming Worksheet is a class). Commented Feb 25, 2010 at 13:11

5 Answers 5

1

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;
Sign up to request clarification or add additional context in comments.

1 Comment

I forgot to say I cannot modify the VB code, just the C# code. As I said, the problem making it a class is that it wastes memory huge time..
1

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).

1 Comment

In fact, my struct is immutable. Note that the only setter in Cell is just calling ws.GetCellValue(x, y) so it doesnt modify itself. It is just the VB.NET compiler which thinks that my struct is mutable, which is wrong, and that is my whole problem :)
1

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".

Comments

0

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.

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.