Why do I need to Instantiate an Object Array Twice? - c#

I have created an Object array like this. But to assign value to object, I have to instantiate each object at every positions of the array? Why do I need this?
This is My method
StageObject[] StageSplitDate = new StageObject[Stages.Rows.Count];
for (int i = 0; i < Stages.Rows.Count; i++)
{
StageSplitDate[i] = new StageObject();
StageSplitDate[i].StageId = "String Value";
StageSplitDate[i].FromTime = StartTime;
StartTime =StartTime.AddMinutes(Convert.ToDouble(10));
StageSplitDate[i].ToTime = StartTime;
}
return StageSplitDate;
And Object Class
public class StageObject
{
public string StageId { get; set; }
public DateTime FromTime { get; set; }
public DateTime ToTime { get; set; }
}

I have to instantiate each object at every positions of the array?
You are not instantiating the array elements twice. In the first line you instantiated an array StageSplitDate with every element set to null.By default each array (of reference types) element is initialized to null. To use it further you need to instantiate each object in the array as well, otherwise you will get null reference exception.
For C#
Arrays (C# Programming Guide) - MSDN
The default value of numeric array elements are set to zero, and reference elements are set to null.
(Since the question was originally tagged for java)
For JAVA
4.12.5. Initial Values of Variables
Each class variable, instance variable, or array component is initialized with a default value when it is created (§15.9, §15.10):
For all reference types (§4.3), the default value is null.

Your array is an array of StageObject references. The StageObjects themselves don't exist yet. Essentially each entry in the array merely "points" to or "refers" to a StageObject.
Before you call new StageObject(), each array element is null, meaning it's referring to nothing.

Think of an analogy where an array is a bookshelf. If you want a shelf of books, just buying the shelf is only the first step; you then need to buy each book and put it on the shelf. Same idea here: allocating the array gives you an empty container, and then you need to create each object and put it into the container.
Why is it like this? Because an initially-empty array is often what you want -- and even if it isn't, unless your object only has a no-arg constructor, Java wouldn't even know how to construct each object.

new StageObject[Stages.Rows.Count] creates a new array of StageObject references containing Stages.Rows.Count null references. You want each element to point to a StageObject. To do that, you need to create some StageObject instances.

StageObject[] StageSplitDate = new StageObject[Stages.Rows.Count];
The above statement only makes reference array for StageObject which are intialized with null but does not actually initanstiate the objects of StageObject
StageSplitDate[i] = new StageObject();
The above statement is creating object of type StageObject and assigns the reference to StageSplitDate element

Related

Passing a value by reference to List.Add()

How could I pass a value by reference to the List?
int x = 2;
List<int> newList = new List<int>();
newList.Add(x);
System.Console.WriteLine(x);
x = 7;
System.Console.WriteLine(newList[0]);
newList[0] = 10;
System.Console.WriteLine(x);
My objective is elements on the list to be related with the previous ones. In C++ I would use a list of pointers, however right now I feel hopeless.
You can't do it with value types.You need to use a reference type.
(change) You can't do it with object too, you need to define your custom class which has a int property. If you use object it will be automatically perform boxing and unboxing.And actual value never affected.
I mean something like this:
MyInteger x = new MyInteger(2);
List<MyInteger> newList = new List<MyInteger>();
newList.Add(x);
Console.WriteLine(x.Value);
x.Value = 7;
Console.WriteLine(newList[0].Value);
newList[0].Value = 10;
Console.WriteLine(x.Value);
class MyInteger
{
public MyInteger(int value)
{
Value = value;
}
public int Value { get; set; }
}
ints are primitives, so you are not passing around a pointer,but the value it self.
Pointers are implicit in C#,so you can wrap ints in an object and pass that object around instead and you will be passing a pointer to the object.
You can't store value types in a .NET generic collection and access them by reference. What you could do is what Simon Whitehead suggested.
I see few solutions of this problem:
1) Create a class which will hold the integer (and possibly other values you might need)
2) Write "unsafe" code. .NET allows usage of pointers if you enable this for your project. This might even require creating custom collection classes.
3) Restructure your algorithm to not require references. E.g. save indexes of values you wish to change.

C# List Objects

I have a list of Character objects I made and a list of Cells which can contain one character. Is it possible for my Character object to be added to the list and be assigned to a cell and changes I make to it in the party list or the cell to effect the object in both place? I don't really know how the pointers will work out for this. I figure what will happen is the object in the list is a separate object from the one assigned to the cell.
Sorry my code is very large so I don't want to post it all here but the Character I am talking about is a custom class I made. I suppose my question really boles down to two questions. When I put something in a list is that changing where the pointer points or is that a new object all together. Also can I have multiple pointer if I add something to a list then assign that to another instance of the character object will referencing the Character from the Cell Object be the Same as referencing my Character from the other list object.
As long as your Character is a class (i.e. a reference type) then you are essentially storing references to Character objects. Any changes you make to an object through a reference to it will be visible when the object is accessed through any other reference.
Example:
class Character
{
public string Name { get; set; }
}
var c = new Character();
var c2 = c;
var arr1 = new Character[] { c };
var arr2 = new Character[] { c };
arr1[0].Name = "Foo";
Console.WriteLine(arr2[0].Name); // "Foo"
Console.WriteLine(c2.Name); // also "Foo"
So basically you want to treat Characters as a reference type.
Just create your own wrapper object which contains a character inside it.
public MyCharacter
{
public char character{get;set;}
}
Objects are treated by reference, so that should work for you.

C# arrays of structs and assignment performance

Suppose I have this code:
struct Normal
{
public float x;
public float y;
}
class NormalContainer
{
public Normal[] Normals
{
get; set;
}
}
class Main
{
void Run( NormalContainer container )
{
Normal[] normals = container.Normals // 1 - see below
normals[5].x = 4; // 3 - see below
container.Normals = normals; // 2 - see below
}
}
Does (1) create a copy of the array or is this a reference to the memory occupied by the array? What about (2) ?
Thanks
Array is a reference type, so you are just copying the reference to the array instance.
An array in C# is a reference type. Items like assignment create copies of the reference vs. the value. At the end of (1) you end up with a local reference to the array stored in container
Note: In C# it's more proper to say "reference to the object" vs. "reference to the memory"
(1) copies the array's reference
(2) same
Array variables are reference types, regardless of their underlying element type, so whenever you assign an array variable to another, you are just copying the reference.

How to get a list of mutable strings?

I have the following piece of code
List<String> l = new List<String>();
String s = "hello";
l.Add(s);
s = "world";
When I set up some breakpoints and go through the program, after executing the last line, the value in the list is still hello instead of world.
Shouldn't it equal world ? Isn't a string an object, and am I not just inserting a pointer into the list? Later on if I change the string to point to a different value ("world"), why is my list still referencing the old value?
How can I get my desired effect ?
Thanks a lot!
Strings are immutable so that won't work. When you attempt to set into it, you actually drop the pointer to the old string and create a new one under the hood.
To get the desired effect, create a class that wraps a string:
public class SortOfMutableString
{
public string Value {get;set;}
public SortOfMutableString(string s)
{
Value = s;
}
public static implicit operator string(SortOfMutableString s)
{
return s.Value;
}
public static implicit operator SortOfMutableString(string s)
{
return new SortOfMutableString(s);
}
}
And use this in your list. Then references will point to the class, but you can contain the string value inside. To make it even better, override implicit casting to and from string so you don't even need to see that you are talking to a SortOfMutableString.
Refer to Jon Skeet's answer for undoubtedly a very accurate explanation about string's in C#, I'm not even going to bother!
Alternative class names:
PseudoMutableString
ICantBelieveItsNotMutable
HappyAndReferenceableString
You're changing the s reference to refer to a different String instance.
Strings are immutable; it is impossible to change the existing instance that you added to the list.
Instead, you can create a mutable StringHolder class with a writable String property.
No, it shouldn't equal world. The value of the variable s is a reference. When you call l.Add(s), that reference is passed by value to the list. So the list now contains a reference to the string "hello".
You now change the value of s to a reference to the string "world". That doesn't change the list at all.
It's important to distinguish between three very different concepts:
A variable (which has a name and a value)
A reference (a value which allows you to navigate to an object, or null)
An object
So in particular, the list doesn't know anything about the variable s - it knows about the value which was passed into Add; that value happened to be the value of s at the time Add was called, that's all.
You may find these articles helpful:
Values and references
Parameter passing in C#
No, there are two different references involved. One called s and one that's at List[0]. When you say l.Add(s) you are setting the list reference to the same address as s, but then when you assign s to "world", then s will point to the new string, leaving List[0] pointing to the old string.
If you really want to do something like what you are asking, you'd need to wrap the string in another object that contains a string, so that s and List[0] both refer to that object, and then that object's reference to a string can change and both will see it.
public class StringWrapper
{
public string TheString { get; set; }
}
Then you can do:
var s = new StringWrapper { TheString = "Hello" };
var l = new List<StringWrapper>();
l.Add(s);
s.TheString = "World";
And now l[0].TheString will be world too. This works because in this case we are not changing the reference in List[0] or s, but they contents of the object referred to by s and List[0].
A variable is an object reference, not an object itself. s = "world" says "make s refer to the string "World") - it does not in any way affect the string "hello" that s was previously referring to. Furthermore, strings in C# are always immutable. You can, however, make the first list element (which currently refers to "hello") refer to a different string: l[0] = "world".
The other two answers here did a great job of saying why what you tried didnt' work, but you were looking for a solution for your desired effect. Wrap a string (property) inside of an object. Then you can change that string and it will be reflected in the collection.

C# Calling a Method, and variable scope

Why is cards being changed below? Got me puzzled.. understand passing by ref which works ok.. but when passing an Array is doesn't do as I expect. Compiling under .NET3.5SP1
Many thanks
void btnCalculate_Click(object sender, EventArgs e)
{
string[] cards = new string[3];
cards[0] = "old0";
cards[1] = "old1";
cards[2] = "old2";
int betResult = 5;
int position = 5;
clsRules myRules = new clsRules();
myRules.DealHand(cards, betResult, ref position); // why is this changing cards!
for (int i = 0; i < 3; i++)
textBox1.Text += cards[i] + "\r\n"; // these are all new[i] .. not expected!
textBox1.Text += "betresult " + betResult.ToString() + "\r\n"; // this is 5 as expected
textBox1.Text += "position " + position.ToString() + "\r\n"; // this is 6 as expected
}
public class clsRules
{
public void DealHand(string[] cardsInternal, int betResultInternal, ref int position1Internal)
{
cardsInternal[0] = "new0";
cardsInternal[1] = "new1";
cardsInternal[2] = "new2";
betResultInternal = 6;
position1Internal = 6;
}
}
Arrays are reference types which in short means the value of the array is not directly contained within a variable. Instead the variable refers to the value. Hopefully the following code will explain this a bit better (List<T> is also a reference type).
List<int> first = new List<int>()( new int[] {1,2,3});
List<int> second = first;
first.Clear();
Console.WriteLine(second.Count); // Prints 0
In this scenario there is a List<int> created on the first line which is referred to by variable first. The second line does not create a new list but instead creates a second variable named second which refers to the same List<int> object as first. This logic applies to all reference types.
When you pass the variable cards into the method you do not pass a copy of the full array but instead a copy of the variable cards. This copy refers to the same array object as the original cards. Hence any modifications you make to the array are visible through the original reference.
A variable of a reference type does
not contain its data directly; it
contains a reference to its data. When
you pass a reference-type parameter by
value, it is possible to change the
data pointed to by the reference, such
as the value of a class member.
However, you cannot change the value
of the reference itself; that is, you
cannot use the same reference to
allocate memory for a new class and
have it persist outside the block. To
do that, pass the parameter using the
ref or out keyword.
http://msdn.microsoft.com/en-us/library/s6938f28(VS.80).aspx
When you are passing a reference type (like an array) to a method by value, you are passing a copy of it's reference. It's still the same object that is referenced, it doesn't create a copy of the array itself.
When passing parameters to methods, there are three different concepts to be aware of:
By Value vs By Reference parameters
Value vs Reference types
Mutable vs Immutable types
In your example, the string array is a Reference type, is a Mutable type, and is passed By Value. The compiler will always let you change the content of the array because it is Mutable. However, since it is a Reference type, the calling code and the called code both point to the same array contents, so the calling code "sees the changes". The fact that it's passed by value in this case is irrelevant, since although the called code's array variable has indeed been passed a copy of the calling code's variable, they both point to the same location in memory.
As other answers have said, it's because a reference is being passed by value.
I have an article on argument passing in C# which you may find useful, in addition to the answers here.
Arrays are reference types, thus are subject to change.
When you are passing an array as an object it is not copied. The receiving method works with the same instance. In a sense arrays are always passed by ref. When an array as well as an instance of any other reference type is passed as a parameter the receiving method gets its own copy of a reference on the same instance of the type. No copy of the actual object is created.
If you need to pass a copy you have to be explicit about this: create a copy yourself or clone the array. The reason it is not done for you is obvious - copying an array can be expensive, you do not want it unless it is really necessary

Categories