I'm trying to fill a buffer with random bytes. The buffer is defined as a list of bytes. This is something that I want to keep as it is. Here is the definition:
namespace NameofProject
{
public partial class Form1 : Form
{
List<byte> buff = new List<byte>();
}
}
And my first attempt is
public static void RandomFillBuffer()
{
Random rnd = new Random();
rnd.NextBytes(buff);
}
Yet this gives such an error for buff:
An object reference is required for the non-static field, method, or property 'Form1.buff'
Then I just deleted the word "static" (I am not sure whether this is true) and it becomes "public void RandomFillBuffer()", but this time I am getting this error for buff:
Argument 1: cannot convert from 'System.Collections.Generic.List' to 'byte[]'
I'd appreciate any help to solve any of the 2 errors if they make sense.
You're getting that problem because NextBytes() expects an array, but you're trying to pass a List<>. One way to solve it would be to change your List<> to an array:
byte[] buff = new byte[someSize];
You're going to have to figure out what someSize should be (it's up to you). You can't fill something without it having a size. Otherwise, how would it know when it's done?
The problem you are having is that NextBytes fills an array[] not a list. You need to define an array with an index of its size
// Put random bytes into this array.
byte[] array = new byte[8];
// Fill array with random bytes.
Random random = new Random();
random.NextBytes(array);
First: you tried to make your method static (it means that this method is not associated with any instance of the object but instead with the class of objects), and tried to reference not static member from it (your buff is not static and thus is associated with a particular instance, a particular Form in your case).
Second: you tried to use Random.NextBytes(System.Byte[]) but provided System.Collections.Generics.List<System.Byte> as an argument.
The code below should work for you (this code assumes at least that buff already has some data and so has a positive length):
var generator = new Random();
var array = new Byte[buff.Count]; // create a local array of the same size as your list
generator.NextBytes(array); // fill the array with random bytes
buff = array.ToList(); // copy array to a new list and let field "buff" reference this freshly created list
Please, note, that this code is not optimal because it copies an array. But it does what you want, I guess.
Related
This question already has answers here:
What is an IndexOutOfRangeException / ArgumentOutOfRangeException and how do I fix it?
(5 answers)
Closed last year.
Here's my code:
using System;
public class Program
{
private static string[] ar = new string[] {};
public static void Main()
{
ar[0] = "hello";
Console.WriteLine("Total array length: " + ar.Length);
}
}
It show the error below when I run the above code:
Run-time exception (line 10): Index was outside the bounds of the array.
I thought that's how to define a dynamic array in C# but I must be missed something here.
You create an empty array, that is an array with fixed length 0 and no entries.
Consider List<string> ar = new List<string>() instead.
Related thread: Dynamic array in C#
EDIT: It later turned out the asker could use a Dictionary<int, string>. For a Dictionary<,>, the set accessor of the indexer (by which I mean the syntax ar[0] = "hello") will either create a new key/value pair (0 → "hello"), or overwrite the value of an already existing key (0).
Declaring private static string[] ar = new string[] {} actually means that you have an array of string with size of 0, i.e., empty array. C# doesn't allow to resize an array so you should initialize the array size if the length is fixed and this the reason you are getting the error Index was outside the bounds of the array. you are trying to set a value to an index which is larger then the array length.
In case the length is not fixed and you want to be dynamic, I recommend using List. Lists use arrays to store the data so you get the speed benefit of arrays with the convenience of a LinkedList by being able to add and remove items without worrying about having to manually change its size.
List<string> myList = new List<string>();
myList.Add("hello");
myList.Add("Ola");
private static string[] ar = new string[] {};
The above will create an empty array of string (i.e. allowed length = 0) and hence the IndexOutOfBound exception.
When you are not certain of the size of your collection, use List.
For e.g.: -
List<string> ar= new List<string>();
ar.Add("hello");
ar.Add("Ola");
Just out of curiosity, coming from C background, I knew that Array cannot be resized.
However, while I see in C#, it's so easy to do like below
var arr = new int[] {1,2,4,6};
arr = new int[2];
Also, there is a method available
Array.Resize(ref arr, 10);
How is it possible?
Thanks!
These operations aren't resizing the array. They're creating a new array of a new size.
Note in the first example that you call new twice. So you're creating two arrays.
In the second example, the documentation explains the same:
This method allocates a new array with the specified size, copies elements from the old array to the new one, and then replaces the old array with the new one.
The source code for the Array class can be found here.
This is the relevant portion:
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;
}
As you can see, it allocates a new array and then copies whatever it can from the existing array into the new array.
Arrays cannot be resized in C#.
Your first example assigns a new array to the variable arr, it doesn't resize the existing array.
Also Array.Resize is a misnomer: it actually creates a new array and copies the values.
The clue to that is with the ref keyword, which indicates that Array.Resize will be reassigning to arr.
Each of those examples actually creates a brand new array, copies the items one by one from the old to the new, and updates the reference.
If you have a collection where the size will change over time, you're almost always better off using a generic List<T>.
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 a class that looks like this:
class MyHash : IComparable
{
public byte[] myBytes = new byte[15];
// constructor
MyHash(byte[] incomingByteArray)
{
for (int i = 0; i <= 15; i++)
{
myBytes[i] = incomingByteArray[i];
}
}
// other irrelevant stuff here
}
Now later when I want to use this class, I try:
MD5 hashMaker = MD5.Create();
byte[] hash = hashMaker.ComputeHash(Encoding.UTF8.GetBytes(thisSubstring));
listOfHashes.Add(new MyHash(hash));
...and Visual Studio (2013) complains that MyHash "does not contain a constructor that takes 1 arguments".
So speaking as something of a c# novice and probably misusing words to boot, I think the MyHash constructor is getting a single reference to 'hash' and what it is expecting is an array...?
I can hack this up to have a constructor with 15 arguments and instantiate it (new MyHash(hash[0],hash[1], etc.)) but that seems like the wrong thing to do and I fear I will pay for it in the programmer after life. I could convert the byte[] into an ArrayList or something but that adds quite an overhead when you're running through that loop millions of times.
I also didn't see a way to specify a specific array length in the constructor (e.g., bytes[15]).
So what is the Correct And True way to send an array of bytes (byte[]) to a constructor?
Thanks very much SO!
change
MyHash(byte[] incomingByteArray)
to
public MyHash(byte[] incomingByteArray)
if you don't include an access modifier such as public or protected, it will be private by default.
I'm receiving some data over a socket and trying to add it to a Queue so it can be dequeued by another thread that is much more slow, something like a buffer.
The problem is that everytime I enqueue a new value, all the values in the queue become that.
byte[] aux = new byte[1464];
aux = (byte[])ar.AsyncState;
//add the package to the package fifo list
lock (lockPktBuffer)
{
packetBuffer.Enqueue(aux);
}
First I thought that I was passing a pointer, so all the entries are just pointing to the same variable.
So I tried to do this:
lock (lockPktBuffer)
{
packetBuffer.Enqueue((byte[])ar.AsyncState);
}
But got the same problem.
Any ideia how to work this out ?
Here is what's going on (see the comments):
// This line creates a new array
byte[] aux = new byte[1464];
// This line "forgets" the new array, and replaces it with ar.AsyncState:
aux = (byte[])ar.AsyncState;
As the result of this, all additions to the queue happen to enqueue the same object returned from ar.AsyncState, producing the effect that you see (all instances in the queue look the same).
Here is how you can fix it:
byte[] aux = ((byte[])(ar.AsyncState).ToArray();
...
packetBuffer.Enqueue(aux);
This call makes a copy of ar.AsyncState into a new array of bytes, making sure that all instances that you enqueue are independent
You are passing a reference. When you assign an array to another, it's the reference that is copied, it doesn't copy the data in the array.
To make a copy of the array you need to specifically copy the data inside it. Example:
// get the reference to the source array
byte[] source = (byte[])ar.AsyncState;
// create a new array with the same size
byte[] aux = new byte[source.Length];
// copy all the values from the source
Array.Copy(source, aux, source.Length);