Reputation: 521
I am having problems with this bit of code
I have this structure
public struct bounds
{
public int xmax = 0;
public int xmin = 0;
public int ymax = 0;
public int ymin = 0;
};
and I make a list out of it
List<bounds> map = new List<bounds>();
I am trying to store the boundaries of a space (or object) in a 2D array (its xmax, xmin, ymin, & ymax) I have this integer y variable which is going to be some number when it gets to this code, but I keep getting red lines under the code associated with my list "map" (i and j are counters for going through the 2D array)
if(!(map.Contains(y))) //if the list doesn't already have this number
{
map.Add(y);
map[y].xmax = i; //and set its xmax, xmin, ymax, ymin
map[y].xmin = i;
map[y].ymax = j;
map[y].ymin = j;
}
if(map[y].xmax < j) // if its already in the list look at the current
map[y].xmax = j; // boundaries and decide if new ones should be set
if(map[y].xmin > j)
map[y].xmin = j;
if (map[y].ymax < j)
map[y].ymax = i;
if(map[y].ymin > j)
map[y].ymin = i;
Upvotes: 0
Views: 327
Reputation: 81105
If the purpose of a data type is to encapsulate a fixed set of related but independent values (such as the coordinates of a point), an exposed-field structure meets that description better than any other data type. Such structures should not have many instance methods other than overrides of ToString()
, Equals()
, and GetHashCode()
; it's generally better for structures to use static utility methods than instance methods. For example, this would be problematical:
public void UpdateRange(Point pt)
{
if (pt.X > xmax) xmax = pt.X;
if (pt.Y > ymax) ymax = pt.Y;
if (pt.X < xmin) xmin = pt.X;
if (pt.Y < ymin) ymin = pt.Y;
}
but this would not:
public void UpdateRange(ref bounds it, Point pt)
{
if (pt.X > it.xmax) it.xmax = pt.X;
if (pt.Y > it.ymax) it.ymax = pt.Y;
if (pt.X < it.xmin) it.xmin = pt.X;
if (pt.Y < it.ymin) it.ymin = pt.Y;
}
Note that when classes expose properties of a structure type, it is not possible to modify such properties directly. One cannot use something like:
bounds.UpdateRange(ref myList[4], newPoint);
nor, if UpdateRange were an instance method, could one use:
myList[4].UpdateRange(newPoint);
In the latter situation, the code would compile, but wouldn't work. Instead, one has to use something like:
var temp = myList[4];
bounds.UpdateRange(ref temp, newPoint);
mylist[4] = temp;
Note that the instance method and the static method with a ref
parameter are semantically identical in the cases where both will compile. The difference between them is that the static method with a ref
parameter will only compile in cases where the ref
parameter is a modifiable variable, but calling the instance method on a property will cause the compiler to copy that property to a temporary variable, call the instance method on that, and discard the result.
I would suggest that your type is almost a perfect example of something that should be a structure. If it were a mutable class type, it would be unclear when code which passed a reference to an instance was really passing the instantaneous values the instance happened to hold at the time of a call, or was passing a reference to a "live" entity. Using an immutable class type or a so-called immutable struct type [note that there isn't really any such thing as an immutable value type] would make methods like UpdateRange
slower to write and to run, while offering no particular benefit.
The one essential thing to note about the structure type is that each field (e.g. xmin
) has no meaning other than "the last value that something stored in "xmin", or zero if nothing has been stored there yet. If code writes 256 to xmin
and -234 to xmax
, then xmin
will hold 256 and xmax -234. Any code which takes a
bounds` and does anything with it should be prepared for such values just as it would be if it took those fields as four separate parameters.
Upvotes: 0
Reputation: 391286
The reason for this is a struct is a value type.
When you're reading out the struct from the list, you're getting a copy.
As such, this line of code (and all that looks like it):
map[y].xmax = i;
is modifying the copy you got out from the list.
You can counter this by manually retrieving the copy, modifying it, and placing it back into the list.
Note: Mutable structs generates all sorts of problems. The problem you're having is just one of them, but you should not make them mutable.
Also note: You're using the struct value itself as an indexer into the list, I assume this is an error, and that you're actually using an index variable, otherwise you're really having problems.
Here's a general tip though. If Visual Studio is drawing red squigglies under your code, you can hover the mouse over it to get a tooltip telling you what is wrong. It may cryptic to you, but the error message can be googled much easier:
Upvotes: 3
Reputation: 69362
To use the List
indexer, you need to pass an int. You're passing a bounds
struct here
map[y].xmax = i;
y
has to be an int representing the index you want to access. I'm guessing y
is a bounds struct because you've used
map.Add(y);
and your map
is of type List<bounds>
.
Upvotes: 0