Whenever you allocate a new array in C# with
new T[length]
the array entries are set to the default of T. That is null for the case that T is a reference type or the result of the default constructor of T, if T is a value type.
In my case i want to initialize an Int32 array with the value -1:
var myArray = new int[100];
for (int i=0; i<myArray.Length; i++) { myArray[i] = -1; }
So after the memory is reserved for the array, the CLR loops over the newly allocated memory and sets all entries to default(int) = 0. After that, my code sets all entries to -1.
That makes the initialization redundant. Does the JIT detect this and neglects the initialization to 0 and if not, is there a way to directly initialize a portion of memory with a custom value?
Referring to C# Array initialization - with non-default value , using Enumerable.Repeat(value, length).ToArray() is no option, because Enumerable.ToArray allocates a new array and copies the values to it afterwards.
Similar to Dan's answer but without the need of using collections:
int[] myArray = Enumerable.Repeat(-1, 100).ToArray();
It's not redundant.
Suppose an exception is thrown during your initialization loop. If the CLR hasn't cleared the memory first, you might be able to "see" the original uninitialized memory, which is a very bad idea, particularly from a security standpoint. That's why the CLR guarantees that any newly allocated memory is wiped to a 0 bit pattern.
The same argument holds for fields in an object, by the way.
I suppose in both cases the CLR could check that you're not going to make the array visible elsewhere before finishing initialization, but it's a complicated check to avoid a pretty simple "wipe this area of memory".
If you buy into Arrays considered somewhat harmful, then your question would be moot as you would write:
var myArray = new List<int>(Enumerable.Repeat(-1, 100));
I highly doubt that the JIT will optimize away the default set for this scenario. The reason being is that this would be an observable difference. Consider the following slightly altered scenario.
obj.myArray = new int[100];
for (int i=0; i<myArray.Length; i++) { obj.myArray[i] = -1; }
It's entirely possible for the loop to throw. At least, it's probably not possible for the JIT to prove it doesn't. If it did throw and the CLR did not default initialize the memory, the result would be observable if you still had a reference to obj.
I suggest using Array.Fill as a very succint way to fill an array with an initial value:
bool[] isPrime = new bool[MaxNum];
Array.Fill(isPrime, true);
This initializes all values in the isPrime array to true.
If you are looking for one liner solution then you could use below:
var myArray = Array.ConvertAll(new int[100], i => -1);
Related
basically I'm trying to append something to an array, but for some reason in wont even work.
(gObject is a thing with a name and a value)
public gObject[] OBJECTS = {};
public void RegisterObjectToRender(gObject reg)
{
OBJECTS.Append<gObject>(reg);
for (int ri = 0; ri < OBJECTS.Length; ri++)
{
Console.WriteLine(OBJECTS[ri].Name);
}
}
I hope everyone who is reading this is having a good day btw
Arrays are fixed size, always. If you want a list: use a list, i.e. use List<Your type> instead of an array. A list has an Add method.
I'm guessing the Append method here is a local extension method that only exists in your code (that isn't a normal API). I'm also guessing that it calls Array.Resize internally, but: that creates a new and different array - it doesn't change the existing array. So if you use that, you'd need to swap the underlying reference afterwards, too - to the new array reference. However, don't do that: Array.Resize is incredibly inefficient, as it allocates a new array every append (contrast List<T> which keeps an oversized backing array, and tracks the count separately, only increasing the underlying array occasionally).
Append returns a new IEnumerable. It does not add to the OBJECTS, but essentially returns a new list. You have to capture the result of Append and use that: var extendedList = OBJECTS.Append(reg).
A better way is to use a list and use Add instead of Append. It is faster and cleaner.
I have a very basic question in C#. So I have an array of int called m_permutation (property of a class), and in a method of the class I have the following code:
int[] newPermutation = new int[m_permutation.Length];
newPermutation = m_permutation;
newPermutation[0] = 5;
I am confused as to why m_permutation is also changed in this code, and how can I fix it ?
I understand that I can initialize newPermutation via a loop for, to get the same values of m_permutation, and that fixes it. However, can somebody explain why this happens, and what is the best fix ?
Thank you,
Bogdan
There's some good, and some bad, about your expectations for your code.
Let's go through what your code is actually doing:
int[] newPermutation = new int[m_permutation.Length];
This will declare a new variable, newPermutation, to be an array of ints, and then construct a new int array containing m_permutation.Length elements.
So far so good.
The next line, not so much:
newPermutation = m_permutation;
This line will actually replace the reference in your array variable newPermutation to, after the assignment, refer to the same array as m_permutation.
Let's consider what an array variable actually is.
When you do this:
int[] x = new int[5];
Then you're doing a couple of things:
You're declaring a variable, x
You're constructing a new object containing the int array
You're assigning the variable, x to refer to this object
After the 2nd line:
newPermutation = m_permutation;
you're essentially saying this:
OK, you know that array we just constructed? Forget that
Let's now refer to this other array, the one that the variable m_permutation is also referring to.
So when this line executes:
newPermutation[0] = 5;
You're essentially saying: The array that newPermutation is now referring to, its first element should now have the value 5.
Since newPermutation at this point refers to the same array as m_permutation, it appears that you're modifying an additional array but in reality you only have one array. You do, however, have two variables referring to the same array.
I recommend you read my answer here regarding pointers since this is relevant.
However, there is an easy fix to your problem.
You can ask for a copy of the array, instead of a reference to the original one.
Simply change your code to this:
int[] newPermutation = m_permutation.ToArray();
The .ToArray() method is guaranteed to return a new array, so this won't be shared with the original.
Bear in mind, however, that if you do this with anything more complex than an int, such as an object, you're only getting copies of the object references, not the objects themselves. You can get back to Stack Overflow with new questions when/if you get to this point.
Because they both reference the same object in memory.
You can use,
Array.Copy(m_permutation, newPermutation,m_permutation.Length );
I was wandering which way of doing below code is better :
a)
byte[] tmp = BitConverter.GetBytes(Number)
b)
byte[] tmp = new byte[sizeof(Number)]
tmp = BitConverter.GetBytes(Number)
Is it necessary to use dynamic memory allocation ?
Definitely a).
b) creates two arrays, the first of which is completely unnecessary and is thrown away right after being initialized.
Actually second one is redundant, because GetBytes returns a new array so you are throwing away the first array you created...
The first is better for two reasons:
It is more readable
In sample b the first allocation is thrown away as tmp is re-assigned to the return value of GetBytes
Let's say I have a list:
List<object> list = new List();
list.Add(object1);
list.Add(object2);
object foo = list[0];
How do I make a call to list to replace list[0] such that foo will automatically point to the newly replaced object?
I know this line won't do the trick as foo will continue pointing to the old value of list[0]...
list[0] = object3;
Thanks!
It's not possible in my opinion. You need an additonal level of indirection which you have to implement yourself.
You could use a delegate/ anonymous lambda that fetches list[0]:
Func<object> foo = () => list[0];
Of course that changes the syntax slightly since it's now foo() instead of foo but it has the effect that you can fetch the value of list[0] at any time later and it always gets the current value.
What you really want to be able to do is to override the assignment operator but that's not possible in C#. The closest you'll get is to create a class that behaves a bit like Nullable<T> having a .Value property on it and assign to that .Value property instead of overwriting the object itself in the list.
You can use the fixed keyword but only in unsafe code. But i'm not sure what your attempting to do so it may not suite your needs if you need this level of control c++ cli would be a better choice.
Unsafe pointers are one possibility: http://msdn.microsoft.com/en-us/library/y31yhkeb(v=vs.80).aspx
For "safe" code, you can do something like store your value in an array of length 1, and then only store references to the array and always access the value by array[0], but this is a bit of a hack and there is probably a better way to do what you want to accomplish.
I know an int is a value type, but what are arrays of value types? Reference types? Value types? I want to pass an array to a function to check something. Should I just pass the array, as it will just pass the reference of it, or should I pass it as ref?
Arrays are mechanisms that allow you
to treat several items as a single
collection. The Microsoft® .NET Common
Language Runtime (CLR) supports
single-dimensional arrays,
multidimensional arrays, and jagged
arrays (arrays of arrays). All array
types are implicitly derived from
System.Array, which itself is derived
from System.Object. This means that
all arrays are always reference types
which are allocated on the managed
heap, and your app's variable contains
a reference to the array and not the
array itself.
https://msdn.microsoft.com/en-us/library/bb985948.aspx
The simplest test for reference type vs. value type is that reference types can be null, but value types can not.
Arrays (even of value types like int) are reference types in C#.
http://msdn.microsoft.com/en-us/library/aa288453(VS.71).aspx:
In C#, arrays are actually objects. System.Array is the abstract base type of all array types.
First I want to tell you that Array is a reference type. Why? I explain throw one example over here.
Example:
int val = 0; // this is a value type ok
int[] val1 = new int[20] // this is a reference type because space required to store 20 integer value that make array allocated on the heap.
Also reference types can be null whereas value types can't.
value type stored in Stack and reference type stored in Heap
You can pass array to function using out or ref. Only initialize methods are different.
more..
Test to verify if it's a reference or value type:
// we create a simple array of int
var a1 = new int[]{1,2,3};
// copy the array a1 to a2
var a2 = a1;
// modify the first element of a1
a1[0]=2;
// output the first element of a1 and a2
Console.WriteLine("a1:"+a1[0]); // 2
Console.WriteLine("a2:"+a2[0]); // 2
//**************************
// all the two variable point to the same array
// it's reference type!
//**************************
You can test it online: https://dotnetfiddle.net/UWFP45
I would like to add to the other answers that though int[] is a reference type, with the introduction of stackalloc in C# you can allocate an array in stack as a value type. This may give you performance gain since placing array to stack reduces GC pressure (by the way, talking about value types in general you may often hear that value type is allocated in stack; it is not always true:
https://learn.microsoft.com/en-us/archive/blogs/ericlippert/the-truth-about-value-types):
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/stackalloc
A stackalloc expression allocates a block of memory on the stack. A
stack allocated memory block created during the method execution is
automatically discarded when that method returns. You cannot
explicitly free the memory allocated with stackalloc. A stack
allocated memory block is not subject to garbage collection and
doesn't have to be pinned with a fixed statement.
An example of stackalloc usage:
Span<int> numbers = stackalloc int[10];
for (int ctr = 0; ctr < numbers.Length; ctr++)
numbers[ctr] = ctr + 1;
foreach (int i in numbers)
Console.WriteLine(i);
Using this technique don't forget about the limited stack memory. The link https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/stackalloc provides the necessary information on how to use stackalloc safely considering this limitation.
Additionally, here is an answer that discusses the practical usage of stackalloc: Practical use of `stackalloc` keyword
The array itself is a reference type. The values of that array are value or reference types as determined by the array data type. In your example, the array is a reference type and the values are value types.
All single-dimension arrays implicitly implement IList<T>, where <T> is the data type of the array. You can use that interface as the data type of your method parameter instead. You could also use IEnumerable<T> for the data type. In either case (or even if you just use int[]) you shouldn't need to explicitly pass it as a ref parameter.
//The reference to the array is passed by value. This is the source of the confusion :-)
...
int[] test = { 1, 2, 3, 4 };
modifContenuSansRef(test);
Console.WriteLine(test[0]); // OK --> 99 le contenu du tableau est modifié
modifTailleSansRef(test);
Console.WriteLine(test.Length); // KO --> 4 La taille n'est pas modifiée
}
static void modifContenuSansRef(int[] t)
{
t[0] = 99;
}
static void modifTailleSansRef(int[] t)
{
Array.Resize(ref t, 8);
}
Arrays always are reference types.it does not matter array would contain value type like int or reference type like string.When you declare array for example
int[] integers=new int[10];
integers variable itself contains only reference to the array which will reside in heap.
Also there is many people mention that you could differ value type from reference type just depend on the fact thhat variable could be null or not.
I would like to mention that in the c# currently value types also can be null
for instance
int? integer=null
and it is not good way to identify the type is reference or value only depends on the fact variable could be null or not.
Just a bit of an insight:
For example, int represents a single integer, int[] represents an array of integers.
To initialize the array with specific dimensions, you can use the new keyword, giving the size in the square brackets after the type name:
//create a new array of 32 ints.
int[] integers = new int[32];
All arrays are reference types and follow reference semantics. Hence, in this code, even though the individual elements are primitive value types, the integers array is a reference type. So if you later write:
int[] copy = integers;
this will simply assign the whole variable copy to refer to the same array, it won't create a new array.
C#'s array syntax is flexible, it allows you to declare arrays without initializing them so that the array can be dynamically sized later in the program. With this technique, you are basically creating a null reference and later pointing that reference at a dynamically allocated stretch of memory locations requested with a new keyword:
int[] integers;
integers = new int[32];
Thank You.