static int[] scores = new int[100];
static int[] scorescopy;
public static int orderscores()
{
scorescopy = scores;
Array.Sort(scorescopy);
int sortingtoolb = 0;
return 0;
}
I am trying to get a copy of my initial array and then trying to sort that copy. However, when I use the Array.Sort() function, my first array keeps on being sorted as well, but I would like to preserve it. I tried taking away the new declaration on the scorescopy and that did not effect the result.
Also, is there a way to keep my unused variables within the array as null? (if I am not using all parts of it, I get a bunch of 0's in the beginning of the array).
I am using Visual Studio Express 2012 for Windows 8 on a system running Windows 8.1 Pro.
An array, when assigned, only copies a reference to the same array in memory. You need to actually copy the values for this to work:
public static int orderscores()
{
scorescopy = scores.ToArray(); // Using LINQ to "cheat" and make the copy simple
Array.Sort(scorescopy);
int sortingtoolb = 0;
return 0;
}
Note that you can do this without LINQ via:
scorescopy = new int[scores.Length];
Array.Copy(scores, scorescopy, scores.Length);
//... rest of your code
The expression scorescopy = scores; duplicate the handle to the array.
if you want to create a copy of the array items you should change that line to:
scores.copyTo(scorescopy,0);
You still need to make sure scorecopy has enough room to store the items.
so you also need this expression: static int[] scorescopy = new int[scores.Length];
and now your code should like this:
static int[] scores = new int[100];
static int[] scorescopy = new int[scores.Length];
public static int orderscores()
{
scores.copyTo(scorescopy,0);
Array.Sort(scorescopy);
int sortingtoolb = 0;
return 0;
}
You are getting a pointer to the same array, you want a clone:
scorescopy = (int [])scores.Clone();
Related
I just came across a situation that boils down to this:
private static uint[] intArray;
private static void Main(string[] args)
{
intArray = new uint[10];
for(var i = 0u; i < intArray.Length; i++)
{
intArray[i] = i;
}
ref var value = ref intArray[4];
Array.Resize(ref intArray, 100);
value += 10; // what are we modifying here? The old memory?
Console.WriteLine(intArray[4]); // prints 4 not 14 because the array is resized
}
Is this the intended behavior for ref variables in C#?
Yes, this is expected. Array.Resize() does not literally resize the array, it can't, an array is contiguous memory. What it does is create a new array with the required size and copy the values from the old array into it. As explained here: https://learn.microsoft.com/en-us/dotnet/api/system.array.resize?view=netframework-4.8
You also have the question in the comment: "what are we modifying here? The old memory?" Yes, although you have no way of accessing the old array, there is still your reference to the element within it, so the GC cannot delete it until value goes out of scope. So there is no error from updating the contents.
int is a value type, so the value is copied to the new array. If you had an array of Object the value of the reference would be copied and you could still access that through your variable value.
I have a c# class that looks like this:
public class MemberData
{
public int meme_ck;
public string meme_name;
public bool meme_active;
public MemberData(int ck2, string name2, bool active2)
{
meme_ck = ck2;
meme_name = name2;
meme_active = active2;
}
}
I have made two arrays out of that class:
private MemberData[] memarray1 = new MemberData[10000];
private MemberData[] memarray2 = new Memberdata[10000];
Over the course of my application I do a bunch of stuff with these two arrays and values change, etc. Member's name or active status may change which results in the ararys becoming different.
Eventually I need to compare them in order to do things to the other one based on what results are kicked out in the first one.
For example, member is de-activated in the first array based on something application does, I need to update array 2 to de-activate that same member.
I am trying to use some database design philosphy with the int CK (contrived-key) to be able to rapidly look up the entry in the other array based on the CK.
Since I can't figure it out I've had to resort to using nested for loops like this, which sucks:
foreach (Memberdata md in memarray1)
{
foreach (Memberdatamd2 in memarray2)
{
if (md.ck = md2.ck)
{
//de-activate member
}
}
}
Is there a better way to do this? I just want to find the index in the second array based on CK when I have the CK value from the first array.
Any other tips or advice you have about structure would be appreciated as well. Should I be using something other than arrays? How would I accomplish this same thing with Lists?
Thanks!
Should I be using something other than arrays?
Yes. Don't use arrays; they are seldom the right data structure to use.
How would I accomplish this same thing with Lists?
Lists are only marginally better. They don't support an efficient lookup-by-key operation which is what you need.
It sounds like what you want is instead of two arrays, two Dictionary<int, MemberData> where the key is the ck.
I totally agree with Eric Lippert's answer above. It is better you do not use Array.
Same thing can be achieved using List<MemberData>. You can use LINQ as well to query your DataStructure.
Following is one of the way just to achieve your result using array
class Program
{
static MemberData[] memarray1 = new MemberData[10000];
static MemberData[] memarray2 = new MemberData[10000];
static void Main(string[] args)
{
for (int i = 0; i < memarray1.Length; i++)
{
memarray1[i] = new MemberData(i + 1, "MemName" + i + 1, true);
memarray2[i] = new MemberData(i + 1, "MemName" + i + 1, true);
}
// SIMULATING YOUR APP OPERATION OF CHANGING A RANDOM ARRAY VALUE IN memarray1
int tempIndex = new Random().Next(0, 9999);
memarray1[tempIndex].meme_name = "ChangedName";
memarray1[tempIndex].meme_active = false;
//FOR YOUR UDERSTADNING TAKING meme_ck IN AN INTEGER VARIABLE
int ck_in_mem1 = memarray1[tempIndex].meme_ck;
//FINDING ITEM IN ARRAY2
MemberData tempData = memarray2.Where(val => val.meme_ck == ck_in_mem1).FirstOrDefault();
// THIS IS YOUR ITEM.
Console.ReadLine();
}
}
I have this C# program, and it has the following code:
/*10 data for one peprson */
private int[] data = new int[10];
private void SomeMethod()
{
/*More code*/
this.data = new int[10];
/*More code*/
}
This program calls this method when an event occurs, and every time that happens, this one-dimensional array gets a "new" instance of an array of size 10, and refresh the array. Kinda like resetting it.
Now, I was told to write a new program that does the same thing, except that there are 5 people now. So I created a 2-dimensional array like
private int[,] data = new int[5, 10];
which will be able to store 10 data for each of the 5 people.
Now I am at a loss on how to refresh/reset only one person's data from this 2-d array. I tried
private void SomeMethod(int index) /*index 0 - 4 for each of the 5 people*/
{
this.data[index] = new int[10];
}
but this clearly does not work, and I get an error saying I am missing a dimension. Is there a way to achieve this?
For the time being, I am using
private void SomeMethod(int index) /*index 0 - 4 for each of the 5 people*/
{
for(int i=0; i<10; i++)
this.data[index, i] = 0;
}
When I tested it with the original code, I noticed that every time it got a "new" instance, it was assigning 0's to the array. Now the difference is that the original one is referencing the new instance with no data (and hence 0?), and the rewritten one is overwriting with 0's.
Do these two basically work the same way, program's-function-wise?
There's nothing wrong with the code you have. It's even likely faster than creating the new array. But if you really want to, you can use a jagged array instead:
private int[][] data = new int[5][];
//...
private void SomeMethod(int index) /*index 0 - 4 for each of the 5 people*/
{
this.data[index] = new int[10];
}
But arrays seem weird for this. A List<T> might be better:
private List<int[]> data = new List<int[]>();
where you can then use the .Add() method as you get new records, and use the Count property to know how many you've added.
Moreover, it's common to find out the int[10] array was actually a stand-in for named fields, where each position in the array has meaning. In that situation, you're usually much better off building a class for this data, where each item in the array is a named field in the class (we'll just call it MyClass for now). Then you end up with something like this:
private List<MyClass> data = new List<MyClass>();
I have an array with Length = 3 and with values, for example {1,2,3}.
I need to dynamically resize it.
I know that I can use List or
Array.Resize(). But I need to know how to implement my own resize method?
You can try the following code. Create new array with new size and copy the old array data to the newly created array.
public static Array ResizeArray (Array oldArray, int newSize)
{
int oldSize = oldArray.Length;
Type elementType = oldArray.GetType().GetElementType();
Array newArray = Array.CreateInstance(elementType,newSize);
int preserveLength = System.Math.Min(oldSize,newSize);
if (preserveLength > 0)
{
Array.Copy (oldArray,newArray,preserveLength);
}
return newArray;
}
If this is just for practice then do it. but i suggest you use .Net Array.Resize() if you want to use it in your code. usually .Net libraries are best implemented and optimized.
Any way...you can do it with generic method
private static void Resize<T>(ref T[] array,int size)
{
T[] token = array.Take(size).ToArray(); // attempt to take first n elements
T[] temp = new T[size]; // create new reference
token.CopyTo(temp, 0); // copy array contents to new array
array = temp; // change reference
}
Note that you cannot do this without parameter ref. (The other way is to return array of course)
You may think arrays are passed by reference. thats true. But the references it self are passed by value. so whenever you try to change the reference it does not refer to the original array anymore. you can only change the contents. To make this possible you have to use ref to directly pass the reference into method.
About the code:
{1,2,3} if you resize it to 2 obviously it will remove the last parameter. so you will have {1,2}
if you resize it to 4 then it will give the array with new default values. either null for reference types or 0 for value types (false for Boolean type). here you will have {1,2,3,0}
int[] array = new[] {1, 2, 3};
Resize(ref array,4);
Console.WriteLine(array.Length); // outputs 4
Well, you may look on Array.Resize source code before making your own implementation =)
http://referencesource.microsoft.com/#mscorlib/system/array.cs,71074deaf111c4e3
If you want to resize the array use the build in method Array.Resize().It will be easier and faster.
If you need a dynamically sized data structure, use List for that.
You can always do array.ToList() -> fill the list and do .ToArray() later.
Make an array of the new desired size, copy all items over. Make the variable that referenced your old array reference the new one.
Code from MSDN:
public static void Resize<T>(ref T[] array, int newSize) {
if (newSize < 0) {
throw new ArgumentOutOfRangeException("newSize", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
Contract.Ensures(Contract.ValueAtReturn(out array) != null);
Contract.Ensures(Contract.ValueAtReturn(out array).Length == newSize);
Contract.EndContractBlock();
T[] larray = array;
if (larray == null) {
array = new T[newSize];
return;
}
if (larray.Length != newSize) {
T[] newArray = new T[newSize];
Array.Copy(larray, 0, newArray, 0, larray.Length > newSize? newSize : larray.Length);
array = newArray;
}
}
}
I'm making an inventory system and I'm stuck at the part where the items should be moved from cell to cell by simple drag'n'dropping.
There is an Item[,] Inventory array which holds the items, object fromCell, toCell which should hold the references to cells to operate with when mouse button is released, but when I try doing this:
object temp = toCell;
toCell = fromCell;
fromCell = temp;
...the game is only swapping object references and not the actual objects. How do I make this work?
UPD: Thanks to Bartosz I figured this out. Turns out you can safely use a reference to array of objects and change it with saved indices of objects you wish to swap.
Code can be like this:
object fromArray, toArray;
int fromX, fromY, toX, toY;
// this is where game things happen
void SwapMethod()
{
object temp = ((object[,])toArray)[toX, toY];
((object[,])toArray)[toX, toY] = ((object[,])fromArray)[fromX, fromY];
((object[,])fromArray)[fromX, fromY] = temp;
}
How about this?
internal static void Swap<T>(ref T one, ref T two)
{
T temp = two;
two = one;
one = temp;
}
And all your swapping becomes this.
Swap(Inventory[fromCell], Inventory[toCell]);
Also, you can add the extension for the arrays (if more confortable).
public static void Swap(this Array a, int indexOne, int indexTwo)
{
if (a == null)
throw new NullReferenceException(...);
if (indexOne < 0 | indexOne >= a.Length)
throw new ArgumentOutOfRangeException(...);
if (indexTwo < 0 | indexTwo >= a.Length)
throw new ArgumentOutOfRangeException(...);
Swap(a[indexOne], a[indexTwo]);
}
To use it like so:
Inventory.Swap(fromCell, toCell);
Why not using indexes to your Inventory array: int fromCell, toCell.
var temp = Inventory[toCell];
Inventory[toCell] = fromCell;
Inventory[fromCell] = temp;
You're modeling inventory as 2D array of slots, so it seems fairly safe to use indexes to access it.