I am using a class called BigNumDesc that represents a number. I have a jagged array of that numbers, that represent a matrix.
I first declare this matrix the following way:
BigNumDec[][] matrix = new BigNumDec[][] {
new BigNumDec[] { 1, 2 },
new BigNumDec[] { 3, 4 }
};
Now, I have this method I want to call:
static BigNumDec[][] GetStrictlyUpperTriangle(BigNumDec[][] matrix)
{
BigNumDec[][] newMatrix = new BigNumDec[matrix.Length][];
matrix.CopyTo(newMatrix, 0);
return null;
}
I have a break-point in the last line. If in the watch window, I take any item of matrix, and change it, it will change too newMatrix, as all BigNumDec are reference types(bad design decision from the creator of it?). How can I accomplish this? I need to make modifications to newMatrix, so I must copy it first from matrix.
edit: Tried the same now with ints, but it's happening just the same. I'd it wouldn't happen with value types?
BigNumDec is immutable.
The reason it's still happening with value types is because you're using an array of arrays. You're shallow-copying the "outer" array, which just copies the references to the two "inner" arrays.
You haven't shown whether BigNumDec is immutable or not (I would hope so) but if it is, you should be fine if you just deep copy the array. Alternatively, can you use a rectangular array [,] instead of a jagged array [][]? If so, a simple copy would suffice. There are performance implications with rectangular arrays, mind you - it's worth testing this to see whether it'll be a problem for you. You get better locality of reference, but the actual array access isn't as fast.
The issue is with your initialisation of the BigNumDec array, you are creating a 1-dimensional array of BigNumDec objects. [0] = { 1, 2 }, [1] = { 3. 4 }. You are then effectively copying the references those objects, not their content, hence why the values continue to change.
Change your initialisation to:
BigNumDec[,] matrix = new BigNumDec[,] {
{ 1, 2 },
{ 3, 4 }
};
If your objects are Serializable you can implement deep copy using serialization. It's not very efficient (by performance) but it's simple.
public BigNumDec[][] CopyUsingSerialization(BigNumDec[][] original)
{
var binaryFormatter = new BinaryFormatter();
var serializationStream = new MemoryStream();
binaryFormatter.Serialize(serializationStream, original);
serializationStream.Position = 0;
var copy = (BigNumDec[][])binaryFormatter.Deserialize(serializationStream);
return copy;
}
You have to declare the BigNumDec as [Serializable]:
[Serializable]
public class BigNumDec
{
//class content
}
(as said in other answers here, if you can move to two dimensional array instead of jagged you'll get better solution)
Related
I just have a question. I noticed that unlike C++, C# is a bit complicated when it comes to array. One of the features or techniques I've been looking for in the array is that: I want to add elements or remove elements from it in a more efficient and simpler way.
Say for example, I have an array called 'food'.
string[] food = {'Bacon', 'Cheese', 'Patty', 'Crabs'}
Then I decided to add more food. Problem with C# as I can see it is this isn't possible to do unless you do use an ArrayList. How about for an array itself? I want to use the array as some sort of inventory where I add things.
Thanks a lot!
You can't do that with arrays in C# without allocating a new array. Because arrays are fixed in size.
If you want to be able to add/remove elements from a container, you could use List<T>. Alternativly you could use an ArrayList but that is not recommended, since in most cases List<T> has a performance advantage.
Internally both use an array as the default container for your data. They also take care of resizing the container according to how much data you put in the collection or take out.
In your example, you would use a list like
List<string> food = new List<string> { "Bacon", "Cheese", "Patty", "Crabs" };
food.Add("Milk"); //Will add Milk to the list
food.Remove("Bacon"); //Will remove "Bacon"
List on MSDN: Docs
Ideally, if you are going to have a variable size array of strings, a List would be better. All you would have to do is then call list.Add(""), list.Remove(""), and other equivalent methods.
But if you would like to keep using string arrays, you could create either a function or class that takes an array, creates a new array of either a larger or smaller size, repopulate that array with the values you had from the original array, and return the new array.
public string[] AddFood(string[] input, string var)
{
string[] result = new string[input.Length + 1];
for (int i = 0; i < input.Length; i++)
{
result[i] = input[i];
}
result[result.Length - 1] = var;
return result;
}
public string[] RemoveFood(string[] input, int index)
{
string[] result = new string[input.Length - 1];
for (int i = 0; i < input.Length; i++)
{
if (i < index) {
result[i] = input[i];
}
else
{
result[i] = input[i + 1];
}
}
return result;
}
Again, I would highly recommend doing the List method instead. The only down side to these lists is that it appends them to the end, rather then figuring out where you want to place said items.
List<string> myFoods = new List<String>(food);
myFoods.Add("Apple");
myFoods.Remove("Bacon");
myFoods.AddRange(new string[] { "Peach", "Pineapple" });
myFoods.RemoveAt(2);
Console.WriteLine(myFoods[0]);
There is also ArrayList if you want a list more like an array, but it is older code and unfavoured.
ArrayList myFoods = new ArrayList(food);
myFoods.Add("Apple");
myFoods.Remove("Bacon");
myFoods.AddRange(new string[] { "Peach", "Pineapple" });
myFoods.RemoveAt(2);
Console.WriteLine(myFoods[0]);
I hope this helps.
To actually answer the question, you just need to resize the array.
Array.Resize(ref array, );
is the new length of the array
To really add elements to an existing array without resizing you can't. Or, can you? Yes, but with some trickery, which at some point you might say is not worth it.
Consider allocating an array of the size you anticipate it could be. You obviously have to estimate well to avoid tons of unused space. Empty slots in the array would be marked by a sentinel value; for a string the obvious candidate is null. You'd know the "true" size of the array by keeping track of the first index of the sentinel. This suggests that an ArrayWrapper class would encapsulate the array and "true size".
That wrapper could add Add() and AddRange() that replace the sentinel values with real ones without allocating.
All that said, the drawback at some point will be that you have to allocate a new array. Doing this manually using the wrapper is pointless unless you have very specific requirements that allow you to reduce allocations.
So, for the most common cases, stick to a List<>, which does that for you. With the list you can construct it by calling the constructor that takes an initial capacity parameter. Adds will use the underlying array without reallocation until it hits the limit.
In a way that List<> is your wrapper that uses an allocation model the original authors decided would minimize allocations in most cases. That is likely to perform better than anything you write unless you can really leverage your domain.
I read about indexers in MSDN - Indexers which explains how we can use objects like array with index i.e. just like normal Array. However, I think we can create array of objects like
point[] array = new point[100];
So what is the special advantages Indexer over object array?
If all you are after is a collection of objects then an indexer has absolutely no benefit over an array. However, if you need to store state as well as a collection, that's where an indexer shines.
For example, consider the following
public class Tree
{
private Branch[] branches = new Branch[100];
...
public string Name { get; set; }
public Branch this[int i]
{
get
{
return branches[i];
}
}
}
Tree holds an internal collection but also has state of it's own. Having an indexer property allows for simple access to the underlying collection e.g.
tree.Name = "Tree";
var branch = tree[0];
Not in this case that you have mentioned above. However, if you have anything that cannot be represented as an array will be a good example for Indexers to be used.
One .Net framework example is Dictionary. If you see the definition of Dictionary type in .Net you will find that they let you get an access of value through key. So that is a good example of using indexers where the index is presented as string.
Without indexers, how would you do that? of course by index value but it cannot be of type string then, will that be user friendly? I guess not!
So indexers gives you an opportunity to represent your code well.
Similarly, in case of point type, of course you can access the value of by index i.e. 0,1,2...99. What if you want to make more user friendly, such as point["x"]. That is where Indexers will help you.
Another example I could think of how about if you want to access your stack like s1 instead of push and s[0] instead of pop method.
There is a very good example of indexers by Microsoft where you can access file byte by byte by providing character location as index.
http://msdn.microsoft.com/en-us/library/aa288465(v=vs.71).aspx
In your line of code, you've defined an array of point objects, whatever those might be.
point[] array = new point[100];
Assuming you have direct access to the array, you can access the first element in your array like this:
var firstPoint = array[0];
The page you linked to is showing you how you could access that array, if it were defined inside your class, and you didn't have direct access to the array (since it's private).
For example, we could modify the example on that page to use your array:
class SampleCollection
{
private Point[] arr = new Point[100];
public Point this[int i]
{
get { return arr[i]; }
set { arr[i] = value; }
}
}
Then you could access the first element in the array like this:
var sc = new SampleCollection();
var item1 = sc[0];
That isn't an indexer.
An indexer is not used to create an array of objects, it is actually an operator overload to the '[]' operator.
An example for it's use would be if you wanted to make a List wrapper class.
In order to preserve the square braces functionality you would need (and want) to override the square braces operator. This is done via an indexer method.
I have:
List<double> w = new List<double>();
w.Add(1);
w.Add(2);
w.Add(1);
w.Add(4);
w.Add(5);
w.Add(1);
foreach (double num in w)
{
Console.WriteLine(num);
}
Which writes
1 2 1 4 5 1
How do I print the memory location of each number, I tried &num, but get error.
If you're using P/Invoke and you want to pass a list of elements to a C function, you can use attributes in most cases to have the work done for you. Eg.
[DllImport("x.dll")]
extern void PassDoubleArray([MarshalAs(UnmanagedType.LPArray)]Double[] array);
If you have something a bit more complex and need to do it manually, the Marshal class has most of what you need to get it done.
First, allocate some unmanaged memory - enough to store your object or array, using Marshal.AllocHGlobal, which will give you an IntPtr. You can copy .NET primitives to and from the unmanaged memory by using Marshal.Copy. For non primitives, create structs and use Marshal.StructureToPtr to get an IntPtr for it. When you're done with the unmanaged memory, make a call to Marshal.FreeHGlobal to free it up.
eg, this will do the equivalent of the above attribute, but more long-winded.
[DllImport("x.dll")]
extern void PassDoubleArray(IntPtr array);
List<Double> vals = new List<Double>() { ... }
IntPtr unmanaged = Marshal.AllocHGlobal(vals.Length * sizeof(Double));
Marshal.Copy(vals.ToArray(), 0, unmanaged, vals.Length);
PassDoubleArray(unmanaged);
Marshal.FreeHGlobal(unmanaged);
There is now way to get a memory location in c#. Memory addresses are tabu in the .NET Framework, because the garbage collector may rearrange the stuff on the heap.
All you can use in your case is the list index. You could reformulate your loop like:
for (i = 0; i < w.Count; i++) {
Console.WriteLine(w[i]);
}
If you would like to reference an item directly, then use a reference type like:
class MyDouble
{
Public double Num { get; set; }
}
And then declare:
var w = new List<MyDouble>();
w.Add(new MyDouble{Num = 1});
var referenced = new MyDouble{Num = 2};
w.Add(referenced);
a.Add(...);
Console.WriteLine(referenced.Num);
referenced.Num = 7;
There is yet another reason why not to use a memory location. If you add items to the list, the internal array used to store the list items might be resized, i.e. a new array having the double size of the previous one will be created and the items will be copied into the new array. The reference trick shown in my last post, however, would still work.
You'll have to use unsafe code in order for this to work. See here for more details.
Back in the old days of C, one could use array subscripting to address storage in very useful ways. For example, one could declare an array as such.
This array represents an EEPROM image with 8 bit words.
BYTE eepromImage[1024] = { ... };
And later refer to that array as if it were really multi-dimensional storage
BYTE mpuImage[2][512] = eepromImage;
I'm sure I have the syntax wrong, but I hope you get the idea.
Anyway, this projected a two dimension image of what is really single dimensional storage.
The two dimensional projection represents the EEPROM image when loaded into the memory of an MPU with 16 bit words.
In C one could reference the storage multi-dimensionaly and change values and the changed values would show up in the real (single dimension) storage almost as if by magic.
Is it possible to do this same thing using C#?
Our current solution uses multiple arrays and event handlers to keep things synchronized. This kind of works but it is additional complexity that we would like to avoid if there is a better way.
You could wrap the array in a class and write 1-dimensional and 2-dimensional Indexer properties.
Without validations etc it looks like this for a 10x10 array:
class ArrayData
{
byte[] _data = new byte[100];
public byte this[int x]
{
get { return _data[x]; }
set { _data[x] = value; }
}
public byte this[int x, int y]
{
get { return _data[x*10+ y]; }
set { _data[x*10 + y] = value; }
}
}
Yes, but no.
You can allocate a multidimensional array off the bat if you like. You could also create a custom class that allows you to access its underlying data in either a single-dimension or multi-dimensional way, keeping the underlying data in sync.
You cannot, however, access a single-dimensional array with a multi-dimensional index directly.
I have an array:
String[] ay = {
"blah",
"blah number 2"
"etc" };
... But now I want to add to this array at a later time, but I see no option to do so. How can this be done? I keep getting a message saying that the String cannot be converted to String[].
Thank you
Use a List rather than an array:
List<string> list = new List<string>();
list.Add( "blah" ) ;
Then, later, if you really do need it as an array:
string[] ay = list.ToArray();
Arrays are of fixed size, so after it has been created, you can't change the size of it (without creating a new array object)
Use the List<string> instead of the array.
Arrays can't change their size after they are declared. Use collections instead. For example: List.
As everyone's already said, use List in the System.Collections.Generic namespace.
You could also use a Hashtable which will allow you to give each string a meaning, or "key" which gives you an easy way to pull out a certain string with a keyword. (as for keeping messages stored in memory space for whatever purpose.)
You could also Create a new array each time you add a value, make the new array 1 bigger than the old one, copy all the data from the first array into the 2nd array, and then add your new value in the last slot (Length - 1)
Then replace the old array with your new one.
It's the most manual way of doing it.
But List and Hashtable work perfectly well too.
If you don't need indexing a specific array element (usage of brackets), but you want to be able to efficiently add or remove elements, you could use LinkedList.
If you do need indexing
have a look at Dictionary data type also in the System.Collection
http://msdn.microsoft.com/en-us/library/xfhwa508.aspx
so you could do something like
Dictionary<int, string> dictionary = new Dictionary<int, string>();
dictionary.Add(1, "afljsd");
You can do this but I don't recommend it:
// Reallocates an array with a new size, and copies the contents
// of the old array to the new array.
// Arguments:
// oldArray the old array, to be reallocated.
// newSize the new array size.
// Returns A new array with the same contents.
public static System.Array ResizeArray (System.Array oldArray, int newSize) {
int oldSize = oldArray.Length;
System.Type elementType = oldArray.GetType().GetElementType();
System.Array newArray = System.Array.CreateInstance(elementType,newSize);
int preserveLength = System.Math.Min(oldSize,newSize);
if (preserveLength > 0)
System.Array.Copy (oldArray,newArray,preserveLength);
return newArray;
}
Here's an extension method to add the to arrays together and create a new string array
public static class StringArrayExtension
{
public static string[] GetStringArray (this string[] currentArray, string[] arrayToAdd)
{
List<String> list = new List<String>(currentArray);
list.AddRange(arrayToAdd);
return list.ToArray();
}
}