C# Structured List - c#

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;

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:

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

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 abounds` 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.

Related

How can I preserve members of my old class when using implicit conversion casting to set a new value to my object?

I know that some people will suggest other ways of performing this same function and I am only interested in specifically accomplishing my goal. I already have working code that performs said task and just would like to understand more about writing my own powerful objects - thank you.
My goal:
int x = 100;
Base b = new Base(0, 3);
b = x; // Preserves my baseNum of 3 for conversions
Code:
public class Base
{
public int count = 0; // represents the count of current numerical value in base ten digit count : 3 -> could be read NEVER user changed
public int baseNum = 10; // conversion base subscript -> """""
public int represented; // represented base ten value of conversion (used for output NOT mathmatically friendly) -> should be read BUT never change by user
public int numerical = 0;
public int[] basearray; // should NOT be modified read only
public Base()
{
//count = 0; // setting numerical will run digit count
baseNum = 10;
numerical = 0;
}
public Base(int i)
{
baseNum = 10;
numerical = i;
}
public Base(int n, int b)
{
baseNum = b;
numerical = n;
}
public static implicit operator Base(int i)
{
// Help needed
}
public static implicit operator int(Base b)
{
int i = b.numerical;
return i;
}
}
I have excluded much of the irrelevant code. This object holds a numerical value but provides a digit by digit reference to a converted format (as we count in base ten this object converts into other base forms)
What I wish is to preserve the current baseNum member and only update the numerical value of my object when using assignment.
As implicit conversion is a static function as far as I know there is no way to access the instance that will be used when assignments are performed after int is casted into my object.
Is there any way to perform this assignment operation in the way I wish?
Again - I already have many methods that allow me to modify the numerical member of the instance.
I also know that I can simply define the baseNum again after assignment.
I only wish to find out if there is a way to possibly utilize my object in the way I am imagining.
You simply can't do that.
When you write b = x, things happen under the hood are:
take the value if x
invoke implicit operator Base(int i) on the value of x, a Base object is returned
assign the returned object to b
There is no conventional way you can access the original value of b in step 2, where the conversion happens.
Is there any way to perform this assignment operation in the way I wish?
No, there is not. Conversion operators, implicit or explicit, always return a new object. And in the case of your reference type, the value returned is a reference, and the assignment is to variable holding that reference, which does not in any way modify the object that variable previously referred to.
Furthermore, I would suggest you should not want to do this anyway. An assignment that only modifies the target partially would be very confusing to anyone reading the code. At first, maybe just confusing to people unfamiliar with the design, but eventually, once the code's been sitting there for awhile without any need to work on it, even people who were theoretically well-versed in the design will have trouble remembering that it does this.
Stick with what you already have, where modification of individual components of an object are expressed explicitly. This will keep the code expressive, simple, and easy to understand.

C# declaration of variable

I started my journey with C# but I realised that I have some problems with some basic information about memory when it comes to declaration of variables. See if I am correct.
int x; // I declared variable of type int, which name is x. Compiler will provide memory for it but we dont have known value of it.
x=10; // Now memory location is still the same but value now kept there is 10;
public struct Point {
public int x, y;
}
Now I define a struct named Point. Beacuse struct is a value type, it again has reserved memory for it on the computer. Howewer x and y have no value.
Now Point p1 = new Point(); // what is happening here? Struct is not a reference type. So is this just initialization of Point variable with the default constructor without assigning values to x and y?
Second short question. When I write a code like:
int x = 10;
Can I say that I created instance of class integer which value is 10 and name x;
I would be grateful for help.
// what is happening here? Struct is not a reference type. So is this just initialization of Point variable with the default constructor without assigning values to x and y?
No; there are 4 possible scenarios here:
a class: the memory space is wiped to all 0s, then any custom constructor is invoked, which may also involve field initializers
a struct called without a custom constructor: the memory space is wiped to all 0s
a struct called with a custom constructor: the custom constructor is required to assign all the fields
a struct variable used without ever calling a constructor: this is actually a thing, but the calling code must write to all the fields before they can do anything else with it; since most structs do not expose their fields, this rarely works
Second short question. When i write a code like:
int x = 10;
Can i say that i created instance of class integer which value is 10 and name x; I would be grateful for help.
Not really, because in C# terms, int is not a class (it might be in IL terms). Simply: you have declared a local variable of type int with name x and assigned it the value 10, if this is in a method. If this is a class field, then: you have declared a private instance field of type int named x with a field-initializer giving it the value of 10.
Incidentally, you should avoid public fields in general, and mutable fields on structs. You might prefer:
public struct Point {
private readonly int x, y;
public int X { get { return x; } }
public int Y { get { return y; } }
public Point(int x, int y) { this.x = x; this.y = y'; }
}
This will avoid a huge range of problems.
In C# the default struct constructor sets the struct memory to 0, effectively setting all variables to their default values.
In case of ints, it will be 0. For reference types, it will result in null.
(in other words, for any type T it will be default(T)).
Note that when you write a custom constructor in a struct, you must initialize all member fields.
When you write
int x;
this is similar to
Point p1 = new Point(); (considering Point structure is already defined)
in both the cases all integer variables will have default value of 0 and not null, which is is basically what is used in C# to denote 'nothing' and can be assigned only to reference types.
As well, in c# everything is a class, so when you write
int x = 10;
you are creating an instance of class Int32, though the run time will handle this as value type instead of ref type, as special case.
Same is true for other basic types like, Long, DateTime and few others

Allocation of value types

When you assign an instance of a value type to another instance, the object is copied bit-by-bit to the target location:
private struct Word
{
public Word(char c) { ... }
}
public void Method(Word a)
{
Word b = a; //a is copied and stored in b
}
But given the following code:
private Word _word;
public void Method() {
_word = new Word('x');
}
I suspect that the right-hand side (RHS) expression is evaluated first - which instantiates a value type on the stack - and then the value is copied and stored on the location of the _word field, which is on the heap.
The alternative would be to take the left-hand side into consideration, and instantiate the value type directly on _word, avoiding having to copy the object.
Is my suspicion correct? If it is, I suppose it's safe to assume that the first block of code would perform better than the second.
//1 instantiation + 10k copies
Word[] words = new Word[10000];
Word word = new Word('x');
for (int i = 0; i < 10000; i++)
words[i] = word;
//10k instantiations + 10k copies
Word[] words = new Word[10000];
for (int i = 0; i < 10000; i++)
words[i] = new Word('x');
Note: I'm not trying to micro-optimize anything.
Edit: The core of my question is, as Lee puts it: Are structs allocated in place directly, or do they need to be allocated then copied?
When you assign an instance of a value type to another instance, the object is copied bit-by-bit to the target location
When you assign an instance of a value type to a variable of the same type, the value is copied to the target location, yes. But that is true of reference types as well: the reference is copied bit by bit to the target location. The referent of course stays right where it is.
I suspect that the right-hand side (RHS) expression is evaluated first
The specification states that the left hand side is evaluted to produce a variable, then the right hand side is evaluated to produce a value, and then the assignment happens.
In the examples you give the evaluation of the left hand side does not produce an observable side effect and therefore its evaluation can be re-ordered by the optimizers in the C# compiler, the jitter or the CPU if any of them so choose. But if you had something like
x[i++] = v();
then the side effect on the left hand side has to happen before the call on the right hand side.
The core of my question is: Are structs allocated in place directly, or do they need to be allocated then copied?
The specification states that structures are allocated in a temporary location -- which would typically be the stack or a register in practice -- and then copied to their final destination. However, there are some situations in which the optimizer can determine that it is impossible for the user to notice if the mutation happens "in place" at the final destination. This is a copy elision optimization, and the C# compiler will perform this optimization if it feels it can get away with it.
For more details see my article on the subject:
http://ericlippert.com/2010/10/11/debunking-another-myth-about-value-types/
Are either preferred?
What is the business case for multiple identical structs?
If you need multiple identical objects is a struct the best choice?
A struct (re)initialized in that manner is probably not a good solution for the example use case
In the new array the WordStruct is allocated and initialized using the default ctor (no ctor)
You don't have the option to initialize a struct array with another ctor
If you do need identical structs then this would be preferred
WordStruct[] WordStructS = new WordStruct[1000];
for (int i = 0; i < WordStructS.Length; i++) { WordStructS[i].C = 'x'; }
If multiple identical objects what you really need to do then consider a class
A class new array is allocated but not yet initialized
You don't waste resources initializing with the default constructor
WordClass[] WordClassS = new WordClass[1000];
for (int i = 0; i < WordClassS.Length; i++) { WordClassS[i] = new WordClass('x'); }
If you want to generalize deep copy of an object (struct or class) then consider IConable
In the case of a struct I suspect it is more efficient than a bit wise copy (but I am not positive)
In the case of class it will make a clone (deep copy) not a reference
public struct WordStruct : ICloneable
{
public char C;
public WordStruct(char C)
{
this.C = C;
}
public object Clone()
{
WordStruct newWordStruct = (WordStruct)this.MemberwiseClone();
return newWordStruct;
}
}
I know in a comment you said curiosity but that is not clear in the question
In the question you state first block of code is preferred over the second
I get it is an interesting question of curiosity
But if it is just curiosity then the question should have stopped at
Is my suspicion correct?

Storing an object by reference or workarounds

I am building internal logic for a game in C# and coming from C++ this is something that might be lost in translation for me.
I have an object, Ability that calculates the bonus it provides and returns that as an integer value. The calculation is meant to be dynamic and can change depending on a variety of variables.
public class Ability: Buffable
{
public string abbr { get; private set; }
public Ability(string name, string abbr, uint score) : base(name, score)
{
this.abbr = abbr;
}
// Ability Modifier
// returns the ability modifier for the class.
public int Ability_modifier()
{
const double ARBITARY_MINUS_TEN = -10;
const double HALVE = 2;
double value = (double)this.Evaluate();
double result = (value + ARBITARY_MINUS_TEN) / HALVE;
// Round down in case of odd negative modifier
if (result < 0 && ((value % 2) != 0))
{
result--;
}
return (int)result;
}
I then have another object, Skill which should be aware of that bonus and add it into it's calculation. I wanted to pass an Ability into the constructor of Skill by reference and then store that reference so that if the Ability changed the calculation would as well. The obvious problem with this being that apparently storing references is taboo in C#.
Is there either a work around way to do this or an alternate way to approach this problem that my pointer infested mind isn't considering? I would greatly prefer not to have to pass the ability to the function that evaluates Skill every time, since the one referenced never changes after construction.
The obvious problem with this being that apparently storing references is taboo in C#.
Absolutely not. References are stored all over the place. You're doing it here, for example:
this.abbr = abbr;
System.String is a class, and therefore a reference type. And so the value of abbr is a reference.
I strongly suspect you've misunderstood how reference types work in C#. If you remember a reference to an object, then changes to the object will be visible via the reference. However, changes to the original expression you copied won't be.
For example, using StringBuilder as a handy mutable reference type:
StringBuilder x = new StringBuilder("abc");
// Copy the reference...
StringBuilder y = x;
// This changes data within the object that x's value refers to
x.Append("def");
// This changes the value of x to refer to a different StringBuilder
x = new StringBuilder("ghi");
Console.WriteLine(y); // abcdef
See my articles on references and values, and parameter passing in C# for much more detail.
I am not quite seing enough of your code to give a concrete example, but the way to do this is to pass in a lambda delegate such as () => object.property instead of this: object.property.
In C#, there are reference types and value types. All non-value-type objects are passed by reference, so there should be no issue with references. Just pass it, and it will be passed by reference.

How did the code achieve pass by reference?

Inside main i declared a local int[] array (int[] nums). I did not pass it by reference.
But when i print values of local array i get squared value of each element.
What is the reason for that?
delegate void tsquare(int[] a);
static void Main()
{
int[] nums = { 1, 2, 3 };
tsquare sqr = new tsquare(SomeClass.Square);
sqr(nums);
foreach (int intvals in nums)
{
Console.WriteLine(intvals);
}
}
class SomeClass
{
public static void Square(int[] array)
{
for (int i = 0; i < array.Length; i++)
{
array[i] = array[i] * array[i];
}
}
}
Update:
My appologies to all.What i tought is int[] {Array}is a value type,and the Delegate done
some trick on it.Now from your answer ,i understand Array is Reference type.
There are two concepts here.
Reference types vs. value types
Passing by value vs. passing by reference
Let's tackle the second one first.
Passing something by value means that you give the method its own copy of that value, and it's free to change that value however it wants to, without those changes leaking back into the code that called the method.
For instance, this:
Int32 x = 10;
SomeMethod(x); // pass by value
There's no way x is going to be anything other than 10 after the call returns in this case, since whatever SomeMethod did to its copy of the value, it only did to its own value.
However, passing by reference means that we don't really give the method its own value to play with, rather we give it the location in memory where our own value is located, and thus anything that method does to the value will be reflected back to our code, because in reality, there's only one value in play.
So this:
Int32 x = 10;
SomeMethod(ref x); // pass by reference
In this case, x might hold a different value after SomeMethod returns than it did before it was called.
So that's passing by value vs. passing by reference.
And now to muddle the waters. There's another concept, reference types vs. value types, which many confuses. Your question alludes to you being confused about the issue as well, my apologies if you're not.
A reference type is actually a two-part thing. It's a reference, and it's whatever the reference refers to. Think of a house you know the address of. You writing the address on a piece of paper does not actually put the entire house on that paper, rather you have a "reference" to that particular house on your piece of paper.
A reference type in .NET is the same thing. Somewhere in memory there is an object, which is a set of values, grouped together. The address of this object you store in a variable. This variable is declared to be a type which is a reference type, which allows this two-part deal.
The nice thing about reference types is that you might have many references to the same actual object, so even if you copy the reference around, you still only have one object in memory.
Edit: In respect to the question, an array is a reference type. This means that your variable only holds the address of the actual array, and that array object is located somewhere else in memory.
A value type, however, is one thing, the entire value is part of the "value type", and when you make copies of that, you make distinct copies
Here's an example of value types:
struct SomeType
{
public Int32 Value;
}
SomeType x = new SomeType;
x.Value = 10;
SomeType y = x; // value type, so y is now a copy of x
y.Value = 20; // x.Value is still 10
However, with a reference type, you're not making a copy of the object it refers to, only the reference to it. Think of it like copying the address of that house onto a second piece of paper. You still only have one house.
So, by simply changing the type of SomeType to be a reference type (changing struct to class):
class SomeType
{
public Int32 Value;
}
SomeType x = new SomeType;
x.Value = 10;
SomeType y = x; // reference type, so y now refers to the same object x refers to
y.Value = 20; // now x.Value is also 20, since x and y refer to the same object
And now for the final thing; passing a reference type by value.
Take this method:
public void Test(SomeType t)
{
t.Value = 25;
}
Given our class-version of SomeType above, what we have here is a method that takes a reference type parameter, but it takes it as being passed by value.
What that means is that Test cannot change t to refer to another object altogether, and make that change leak back into the calling code. Think of this as calling a friend, and giving him the address you have on your piece of paper. No matter what your friend is doing to that house, the address you have on your paper won't change.
But, that method is free to modify the contents of the object being referred to. In that house/friend scenario, your friend is free to go and visit that house, and rearrange the furniture. Since there is only one house in play, if you go to that house after he has rearranged it, you'll see his changes.
If you change the method to pass the reference type by reference, not only is that method free to rearrange the contents of the object being referred to, but the method is also free to replace the object with an altogether new object, and have that change reflect back into the calling code. Basically, your friend can tell you back "From now on, use this new address I'll read to you instead of the old one, and forget the old one altogether".
The array reference is passed by value automatically because it is a reference type.
Read:
Reference Types
Value Types
Most of the other answers are correct but I believe the terminology is confusing and warrants explanation. By default, you can say that all parameters in C# are passed by value, meaning the contents of the variable are copied to the method variable. This is intuitive with variables of value types, but the trick is in remembering that variables that are reference types (including arrays) are actually pointers. The memory location the pointer contains is copied to the method when it is passed in.
When you apply the ref modifier, the method gets the actual variable from the caller. For the most part the behavior is the same, but consider the following:
public void DoesNothing(int[] nums)
{
nums = new []{1, 2, 3, 4};
}
In DoesNothing, we instantiate a new int array and assign it to nums. When the method exits, the assignment is not seen by the caller, because the method was manipulating a copy of the reference (pointer) that was passed in.
public void DoesSomething(ref int[] nums)
{
nums = new []{1, 2, 3, 4};
}
With the ref keyword, the method can essentially reach out and affect the original variable itself from the caller.
To achieve what you seemed to originally want, you could create a new array and return it, or use Array.CopyTo() in the caller.
In C#, all parameters are passed by value by default. There are two kinds of types in C#, namely value and reference types.
A variable of reference type when passed as a parameter to a function will still be passed by value; that is if the function changes the object referred to by that variable, after the function completes the variable that was passed in will still refer to the same object (including null) as it did prior to calling the function in the same context.
However, if you use the ref modifier when declaring the function parameter than the function may change the object being referenced by the variable in the caller's context.
For Value types this is more straightforward but it is the same concept. Bear in mind, int[] is a reference type (as are all arrays).
Consider the differences in these functions when passing in some some array of ints:
public static void Square1(int[] array)
{
for (int i = 0; i < array.Length; i++)
{
array[i] = array[i] * array[i];
}
}
public static void Square2(int[] array)
{
array = {10, 20, 30};
for (int i = 0; i < array.Length; i++)
{
array[i] = array[i] * array[i];
}
}
public static void Square3(ref int[] array)
{
array = {10, 20, 30};
for (int i = 0; i < array.Length; i++)
{
array[i] = array[i] * array[i];
}
}
You're not passing it by reference. The array is being passed in by value, but arrays in .NET are reference types, so you're passing in a reference to the array, which is why you're seeing the values squared.
Read the following SO question - it explains the differences between pass-by-value and pass-by-reference. The accepted answer has a link in it to a good article about the topic that should help you understand the difference.
what is different between Passing by value and Passing by reference using C#
Arrays are objects and are passed by reference. Ints are structs and are passed by value (unless you use the ref keyword in your method signature as per the picky guy in the comments) (who was right) (but picky).

Categories

Resources