I found similar topics, but I could not solve the problem I has reading them.
I want to do in C# the same thing like in C is array of pointers, but I do not want to use in C# pointers because it requires to use "unsafe".
How to build an array of " ref to int" that when I change any element of that array then I will also change that what it refs to at the same time the variable that it points to ( Like in C - array of pointers).
Best regards,
Chris
If performance is not a concern, than one common workaround is to use lambda to capture the access to value type variable:
Sample:
class GetSetPair<T>
{
public Func<T> Get {get;set;}
public Action<T> Set {get;set;}
}
var referencesToInt = new List<GetSetPair<int>>();
int value = 42;
referencesToInt.Add(new GetSetPair<int>{Get=()=>value, Set = v => value = v});
referencesToInt[0].Set(33);
Console.WriteLine(value); // 33
value = 22;
Console.WriteLine(referencesToInt[0].Get()); //22
Arrays are reference types, and therefore you can pass around references to that array. For example, given the following program:
public class Program
{
public static Random rnd = new Random();
public static int[] array2;
public static void Main()
{
int[] array = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
PrintArray(array);
array[4] = rnd.Next();
PrintArray(array);
ModArray(array, 2);
PrintArray(array);
array2 = array; //This makes array2 reference array1
ModArray(array2, 8); //Operate on the array2 reference
PrintArray(array); //Changes are reflected in array
PrintArray(array2); //And in array2
Console.ReadKey(true);
}
public static void PrintArray(int[] array)
{
foreach (var e in array)
Console.Write(e + ", ");
Console.WriteLine();
}
public static void ModArray(int[] array, int i)
{
array[i] = rnd.Next();
}
}
Will give the following output:
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, <- Original
1, 2, 3, 4, 744477516, 6, 7, 8, 9, 10, <- Modified in Main
1, 2, 102109069, 4, 744477516, 6, 7, 8, 9, 10, <- Modified in ModArray
1, 2, 102109069, 4, 744477516, 6, 7, 8, 1776657318, 10, <- array, after modifying array2
1, 2, 102109069, 4, 744477516, 6, 7, 8, 1776657318, 10, <- array2
So in a sense, you can pass around a reference to the array, modify that reference, and have it reflected in all of its copies.
The caveat here is that anybody who "owns" a reference to the original array cannot reassign that array (or resize it). It can modify the elements of the array, but it can't make the original array point to a new instance (which is what happens when it is resized). Also, as Jon Skeet mentioned in his comment, the danger is that if you were doing this in a different method other than Main, if the array goes out of scope, what would happen to array2?
See Also:
Is int[] a reference type or a value type?
Are arrays or lists passed by default by reference in c#?
Related
I can not understand the difference between the declaration with array initialization in the first case and the second
int[] array = new int[3] { 1, 2, 3 };
int[] secondArray = { 1, 2, 3 };
They seem to do the same thing, maybe they work differently?
The is no difference in the result between the two show lines shown:
int[] array = new int[3] { 1, 2, 3 };
int[] secondArray = { 1, 2, 3 };
However, there are practical differences between new int[n] {...} syntax and {...}:
Implicit type is not available for the alternative array initialiser:
var a1 = new int[3] { 1, 2, 3 }; // OK
var a2 = { 1, 2, 3 }; // Error: Cannot initialize an implicitly-typed variable with an array initializer
// BTW. You can omit the size
var a3 = new int[] { 1, 2, 3 }; // OK
With the alternative syntax you cannot specify the size, it's always inferred.
var a1 = new int[100]; // Array with 100 elements (all 0)
int[] a2 = { }; // Array with no elements
There is no difference in the compiled code between the two lines.
The second one is just a shortcut. Both statements have the same result. The shorter variant just wasn't available in early versions of C#.
The first one uses 3 as a array size explictly, the 2nd one size is inferred.
This might be work if you dont want to initialize the values.
There is no difference between this two array initialization syntaxes in terms how they will be translated by the compiler into IL (you can play with it at sharplab.io) and it is the same as the following one:
int[] thirdArray = new int[] { 1, 2, 3 };
The only difference comes when you are using those with already declared variable, i.e. you can use 1st and 3rd to assign new value to existing array variable but not the second one:
int[] arr;
arr = new int[3] { 1, 2, 3 }; // works
// arr = { 1, 2, 3 }; // won't compile
arr = new int[] { 1, 2, 3 }; // works
Given a 1D array,
double[] arr = { 4, 3, 2, 8, 7, 6, 1 };
I want to get values from 2nd index till last and want to store the array in a variable.
Want to get something like this:
new_arr = {3, 2, 8, 7, 6, 1 }; //first element sliced
You can use C# 8 indices and ranges feature
double[] arr = { 4, 3, 2, 8, 7, 6, 1 };
var slice = arr[1..];
It'll return all items from index 1 till the end of array and give you an expected slice {3, 2, 8, 7, 6, 1 }. Again, it works only with C# 8 and .NET Core 3.x.
For earliest versions of C# you should do this by yourself, using Array.Copy for example or System.Linq
double[] arr = { 4, 3, 2, 8, 7, 6, 1 };
var slice = arr.Skip(1).ToArray();
If you are using C# 8, you can use Indices & Range. It goes something like this:
var newArray = oldArray[1..]; // Takes everything from index 1 until the end.
You can use Linq to skip the fist item and take the rest. This will give you the sequence:
arr.Skip(1);
Which you can convert to a new array like this:
var new_arr = arr.Skip(1).ToArray();
I usually spend my time reading and trying to answer the Excel VBA questions but I am trying to learn C# now. Can someone help me understand why I get a StackOverflowException error on the second to last line in my code?
I am trying to fill an array via a method.
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
int[] numbers = GenerateNumbers();
Console.WriteLine(numbers);
Console.ReadKey();
}
static int[] GenerateNumbers()
{
int[] num = new int[10] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
return GenerateNumbers();
}
}
}
You are confusing the weird VBA way of returning functions with C#. You are returning an infinite recursion, which can be easily fixed by using this:
static int[] GenerateNumbers()
{
int[] num = new int[10] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
return num; //you don't return the function name but a variable
}
A stack overflow is an undesirable condition in which a particular
computer program tries to use more memory space than the call stack
has available. In programming, the call stack is a buffer that stores
requests that need to be handled. http://whatis.techtarget.com/definition/stack-overflow
static int[] GenerateNumbers()
{
int[] num = new int[10] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
return GenerateNumbers(); //Here is where the problem happens
}
The problem lies with the return part. You are calling the same function in the same function creating a stack of the same function again and again and... You get the picture.
Change it to
return num;
By calling return GenerateNumbers() at the end of your function, you are running that function over and over again infinitely because there is no way to break the recursion, causing the stack overflow. You should instead use return num
This is what you're esentially doing:
void Main()
{
FlipPage();
}
void FlipPage()
{
FlipPage();
}
So like that blond you keep flipping that page in all eternity
I have two arrays, one singular and the other 2 dimensional.
int[][] array1 = {
new int [] {1, 22, 3, 44, 5, 66},
new int [] {11, 22, 33, 44, 55, 66},
new int [] {1, 2, 3, 4, 5, 6},
};
int[] array2 = new int[] {1, 2, 3, 5, 66}
I need to create a loop which searches the array1 for both the 2nd last digits in array2, so it would return how many times an array with array1 contains both 5 and 66, which is 1, as the other two only contain 1 of each number.
I already managed to write a function which returns how many times array2 as a whole exists in array1, this new function is effectively a refinement of that.
for (int a = 0; a < array1[i].Length; a++)
{
for (int b = 0; b < array2.Length; b++)
{
if (array2[c] == array1[a][b])
count++;
temp[b] = array1[a][b];
}
}
I feel all would be needed to search for just the last two digits is a slight change to this function, I tried to add in another loop but that didn't work either. How would I go about doing this? I'm using loops and not Contains for a reason since i'm still learning the basics.
The one thing is not clear in question that, does it matter which position the two digits occur in the 2D array?
If ithis is not the case, then you can use Intersect() which produces the set intersection of two sequences by using the default equality comparer to compare values:
var result = array1.Count(x => x.Intersect(array2.Reverse().Take(2)).Count() == 2);
If you have paid an attention we have used this line, for getting last two elements of array1:
array1.Reverse().Take(2);
.NET Fiddle
Additional:
If you want to find if last two elements of arrays in 2D array is equal to last two elements of array1, then you can try LINQ solution:
var result = array1.Count(x=> x.Reverse().Take(2).SequenceEqual(array2.Reverse().Take(2)));
Explanation of used extension methods:
Reverse() inverts the order of the elements in a sequence.
Take() returns a specified number of contiguous elements from the start of a sequence.
SequenceEqual() determines whether two sequences are equal by comparing the elements by using the default equality comparer for their type.
After getting last two elements of both arrays, we will use SequenceEqual() to determine if both arrays are equal.
var res = array1.Where((x) => (x.Contains(array2.Last()) && x.Contains(array2[array2.Length - 2]))).Count();
Explaination:
array1.Where takes every subarray of array1 and filters the ones that
meet a certain condition. The condition being every subarray of
array1 contains the last && next-to-last element of array2.The
Count() methods returns the number of subarrays that meet the
conditions
You can create an array of target values and then count the number of times that the intersection of that array with each subarray in the 2D array contains all the items in the target array:
using System;
using System.Linq;
namespace ConsoleApplication2
{
class Program
{
[STAThread]
private static void Main()
{
int[][] array1 =
{
new [] {1, 22, 3, 44, 5, 66},
new [] {11, 22, 33, 44, 55, 66},
new [] {1, 2, 3, 4, 5, 6},
new [] {1, 66, 3, 4, 5, 6} // This one has the target items out of order.
};
int[] array2 = {1, 2, 3, 5, 66};
// Extract the targets like this; it avoids making a copy
// of array2 which occurs if you use IEnumerable.Reverse().
int[] targets = {array2[array2.Length - 2], array2[array2.Length - 1]};
// Count the number of times that each subarray in array1 includes
// all the items in targets:
int count = array1.Count(array => array.Intersect(targets).Count() == targets.Length);
Console.WriteLine(count);
}
}
}
Let's say that I have an array of strings like this:
1, 2, 3, 4, 5, 6, 7, 8
and I want to shift the elements of the array such that
The first element always remains fixed
Only the remaining elements get shifted like so ...
The last element in the array becomes the 2nd element and is shifted through the array with each pass.
Pass #1: 1, 2, 3, 4, 5, 6, 7, 8
Pass #2: 1, 8, 2, 3, 4, 5, 6, 7
Pass #3: 1, 7, 8, 2, 3, 4, 5, 6
Pass #4: 1, 6, 7, 8, 2, 3, 4, 5
Any assistance would be greatly appreciated.
Because this looks like homework, I'm posting an unnecessary complex, but very hip LINQ solution:
int[] array = new int[] { 1, 2, 3, 4, 5, 6, 7, 8 };
int[] result = array.Take(1)
.Concat(array.Reverse().Take(1))
.Concat(array.Skip(1).Reverse().Skip(1).Reverse())
.ToArray();
Probably the fastest way to do this in C# is to use Array.Copy. I don't know much about pointers in C# so there's probably a way of doing it that's even faster and avoids the array bounds checks and such but the following should work. It makes several assumptions and doesn't check for errors but you can fix it up.
void Shift<T>(T[] array) {
T last = array[array.Length-1];
Array.Copy(array, 1, array, 2, array.Length-2);
array[1]=last;
}
EDIT
Optionally, there is Buffer.BlockCopy which according to this post performs fewer validations but internally copies the block the same way.
Because this looks like homework, I'm not going to solve it for you, but I have a couple of suggestions:
Remember to not overwrite data if it isn't somewhere else already. You're going to need a temporary variable.
Try traversing the array from the end to the beginning. The problem is probably simpler that way, though it can be done from front-to-back.
Make sure your algorithm works for an arbitrary-length array, not just one that's of size 8, as your example gave.
Although sounds like homework like others suggest, if changing to a List<>, you can get what you want with the following...
List<int> Nums2 = new List<int>();
for( int i = 1; i < 9; i++ )
Nums2.Add(i);
for (int i = 1; i < 10; i++)
{
Nums2.Insert( 1, Nums2[ Nums2.Count -1] );
Nums2.RemoveAt(Nums2.Count -1);
}
Define this:
public static class Extensions
{
public static IEnumerable<T> Rotate<T>(this IEnumerable<T> enuml)
{
var count = enuml.Count();
return enuml
.Skip(count - 1)
.Concat(enuml.Take(count - 1));
}
public static IEnumerable<T> SkipAndRotate<T>(this IEnumerable<T> enuml)
{
return enum
.Take(1)
.Concat(
enuml.Skip(1).Rotate()
);
}
}
Then call it like so:
var array = new [] { 1, 2, 3, 4, 5, 6, 7, 8 };
var pass1 = array.SkipAndRotate().ToArray();
var pass2 = pass1.SkipAndRotate().ToArray();
var pass3 = pass2.SkipAndRotate().ToArray();
var pass4 = pass3.SkipAndRotate().ToArray();
There's some repeated code there that you might want to refactor. And of course, I haven't compiled this so caveat emptor!
This is similar to Josh Einstein's but it will do it manually and will allow you to specify how many elements to preserve at the beginning.
static void ShiftArray<T>(T[] array, int elementsToPreserve)
{
T temp = array[array.Length - 1];
for (int i = array.Length - 1; i > elementsToPreserve; i--)
{
array[i] = array[i - 1];
}
array[elementsToPreserve] = temp;
}
Consumed:
int[] array = { 1, 2, 3, 4, 5, 6, 7, 8 };
ShiftArray(array, 2);
First pass: 1 2 8 3 4 5 6 7