I'm trying to convert a c++ code into c# and I encountered a double pointer. I'm wondering how can double pointers be implemented in c#?
if I have say,
MyClass **MyClasses;
and it was initialized like this.
MyClasses = new MyClass*[ClassNums];
in another function inside the class, every subitems were initialized in a loop.
for(num = 0; num < classnum; num++)
{
MyClasses[subnum] = new MyClass();
}
and this double-pointer is being used like this.
MyClasses[subnum]->MyMethod();
How can this be converted into c#? I tried to use an array of MyClasses[] but i'm not quite sure about it. Also, I cannot test this because it's from a static library and the components which are using it are not yet converted into c#. Should I use generic lists or something?
In this case, the outer pointer is being used to illustrate a spannable range, as shown in the loop here:
for(num = 0; num < classnum; num++)
{
MyClasses[subnum] = new MyClass();
}
So the outer pointer should probably be replaced by a list, array or IEnumerable<T> sequence.
The inner pointer is being used to direct to an object, so that should be replaced with a reference.
So: unless there is something very specific that the C++ code is doing, all you need here is:
MyClass[] arr = ...
...
for(int i = 0, i < arr.Length ; i++)
{
arr[i] = new MyClass();
}
...
arr[i].MyMethod();
Note that this can only be interpreted by looking at the code. There are other possible ways to talk about "double pointers*; consider this ref example:
void SomeMethod(ref MyClass obj) {...}
Here obj is a reference to a reference (to a MyClass)–with everything being double-dereferenced automatically (or a single-dereferencing assignment if you change the value of obj). This too would be comparable to a double-pointer.
Related
For an experiment, I tried this :
(1) Create 100000 classes, each of them wrapping a double variable
---This is the experiment part---
(2) Measured performance of two methods by running 100000 times :
create a double[] and assign the value of wrapped variables.
create a class[] and assign the reference of wrapping class.
The above may confuse you, so I am attaching the code :
static void Main(string[] args)
{
int length = 100000;
Test test = new Test(length);
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for (int i = 0; i < length; i++)
test.CopyValue();
//test.CopyReference(); //test.CopyValue(); or test.CopyReference();
stopwatch.Stop();
Console.WriteLine("RunTime : {0} ", stopwatch.ElapsedMilliseconds);
}
class DoubleWrapper
{
public double value = 0.0;
}
class Test
{
DoubleWrapper[] wrapper;
public void CopyValue()
{
double[] x = new double[wrapper.Length];
for (int i = 0; i < wrapper.Length; i++)
x[i] = wrapper[i].value;
}
public void CopyReference()
{
DoubleWrapper[] x = new DoubleWrapper[wrapper.Length];
for (int i = 0; i < wrapper.Length; i++)
x[i] = wrapper[i];
}
public Test(int length)
{
wrapper = new DoubleWrapper[length];
for (int i = 0; i < length; i++)
wrapper[i] = new DoubleWrapper();
}
}
The result is as follows :
test.CopyValue() : 56890 (millisec)
test.CopyReference() : 66688 (millisec)
(built with release configuration and ran exe)
I tried several times, but the result doesn't change much.
So I concluded that CopyReference() takes longer time.
But I hardly understand why. Here is the question :
I thought that, regardless of CopyValue() or CopyReference(), what my machine does is "Copying a number in memory" though one is double value and the another is reference to a class. So there should not be meaningful difference in performance, but the fact is not.
Then what is the difference between copying a value and copying a reference?
Does copying a reference do more thing than copying a value?
(When passing a reference without ref keyword, isn't it true that reference is copied as if it were value? What I am saying is that,
ClassA x = new ClassA();
ClassA y = x;
means making a copy of "reference of x" and then assigning to variable y, consequently y = null doesn't affect x at all. Is this true?)
If I am working with wrong assumptions, please let me know what I am wrong with.
I appreciate your help and advice.
-
I guessed that GC might have some impact, but turning off GC by TryStartNoGCRegion(Int64) doesn't change the conclusion.
(both become faster, but still CopyReference() is slower.)
means making a copy of "reference of x" and then assigning to variable
y, consequently y = null doesn't affect x at all. Is this true?
That's correct - you made a copy of reference.
Now, what about why your implementation of CopyReference is slower.
You have to do performance analysis to get real insight about it, but on top of my head:
You're creating a new instance of DoubleWrapper reference type, inside that method.
Remember, that C# is not "zero-cost abstraction" language, like C/C++/Rust might be.
Creating an instance of, even simple reference type, that does nothing more than a simple wrapper over a primitive type, suppose to cost you more. Because that instance has more in it than a simple double value - the size of DoubleWrapperobject will not be equal to 8 bytes.
Reading about the stack and the heap may help you understand. if you copy a reference, you essentially copy the pointer showing to the actual object in the heap, and if that actual object changes, those changes are shown on every thing that references that object.
If you do a "deep copy", or a clone (like when implementing IClonable) you will duplicate that data in the stack and create a pointer to it, thus not beeing dependant on the original object any longer.
I hope this explanation helps you a little bit? See this for some information https://www.c-sharpcorner.com/article/C-Sharp-heaping-vs-stacking-in-net-part-i/ on the stack and heap.
The scenario is that I have say two different types of cases - case 1 and case 2. For case 1 and case 2 each I have a certain startIndex, endIndex and a formula for accessing the elements of a List.
Now for assigning values startIndex and endIndex I am preferring a normal switch case, however I am at loss for the formula for accessing elements. For case 1 it is say something like List[ a+i ] and for case 2 it is say List[a + (i-b)].
One way can be to have a for loop like this
for(int i=0;;i++)
{
if(case is 1)
then f=a+i
else if(case 2)
then f=a+(i-b)
}
I thought of using delegates. however, as per my knowledge they need to be made global. Actions do not return value. Func can be used but one expression/formula takes only one element (int) and the other takes 3. I need something in lines to this like that anonymous function can be assigned any of above mentioned formulae at runtime from the switch case (as the cases might and will increase in future).
Thank you.
I thought of using delegates. however, as per my knowledge they need
to be made global.
This is not true (actually, there are no truly global variables in C#, since each and every variable needs to be encapsulated inside an object). A public delegate type is indeed visible to all code after referencing the assembly containing this type's code, but a variable of such type can be private.
What I recommend in your situation is to have some sort of mapping from case numbers to delegates. A good idea is to use a Dictionary<TKey, TValue> if you have at most one delegate per case. This dictionary can be stored as a private variable inside the class where your method resides.
public class MyClass
{
private Dictionary<int, Delegate> _delegateMapping = new Dictionary<int, Delegate>;
}
There are a couple of ways you can add elements do the dictionary in the constructor: passing the already populated dictionary, passing an array of delegates, creating these delegates in the constructor itself. Either way, you'll end up with a dictionary of Delegate types, so you'll need to use a cast to be able to use them in your code properly.
for (int i = 1; i < _delegateMapping.Count; i++)
{
switch (i)
{
case 1:
var f = (Action<int>)_delegateMapping[1];
f(i);
break;
case 2:
var f = (Action<int, int>)_delegateMapping[2];
f(i, a);
break;
}
}
Of course I'm greatly improvising here.
It is important to note that if the type of delegate changes inside the dictionary, you will have to modify the cast accordingly inside the switch statement. Otherwise, if no implicit cast exists, you'll get a runtime exception.
Hi guys thank you so very much for your feedbacks. I finally found the solution with Func. This is what my code looks like. I had to manipulate the Func usage a little. I made almost all the vars which I have to use in the Func as global/local to the function where I write these Funcs. My apologies, if I was not able to explain my problem properly.
int i = -1;
Func<int,int> formula = null;
switch(f)
{
case 1:
{
formula = new Func<int,int>(index => { return i; });
}
break;
case 2:
{
formula = new Func<int, int>( index => { return s- (i * c); } );//here s and c are global variables.
}
break;
}
i = startIndex;
while(i < endIndex)
{
var Obj= List[formula.Invoke(i)];
//my code goes here
i++;
}
Let me know if my solution is correct w.r.t performance, logic, C# programming, etc.. :)
EDITED::
#usr and #Kapol I tried the way you suggested and tried to improvise the code like this.
private Dictionary<int, Func<int[], int>> indexFormulae;
private void assignDelegates()
{
indexFormulae = new Dictionary<int, Func<int[], int>>();
indexFormulae.Add(0, getFormula_1);
indexFormulae.Add(1, getFormula_2);
}
private void someFunction(int sp)
{
int i = 0;
Func<int[], int> formula = null;
indexFormulae.TryGetValue(formation,out formula);
i = startIndex;
while (i < endIndex)
{
int[] intValues = new int[] {i,sp,globalVar };
var Obj = List[formula.Invoke(intValues)];
//My code here
i++;
}
}
private int getFormula_1(params int[] intValues)
{
return intValues[0];
}
private int getIndex_Vertical(params int[] intValues)
{
return intValues[1] - (intValues[0] * intValues[2]);
}
So, that with this now I can use these two getFormula methods anywhere in this class rather than keeping them anonymous. and also I think I will stick to params because I might have N number of int params in future for other functions.
How could I pass a value by reference to the List?
int x = 2;
List<int> newList = new List<int>();
newList.Add(x);
System.Console.WriteLine(x);
x = 7;
System.Console.WriteLine(newList[0]);
newList[0] = 10;
System.Console.WriteLine(x);
My objective is elements on the list to be related with the previous ones. In C++ I would use a list of pointers, however right now I feel hopeless.
You can't do it with value types.You need to use a reference type.
(change) You can't do it with object too, you need to define your custom class which has a int property. If you use object it will be automatically perform boxing and unboxing.And actual value never affected.
I mean something like this:
MyInteger x = new MyInteger(2);
List<MyInteger> newList = new List<MyInteger>();
newList.Add(x);
Console.WriteLine(x.Value);
x.Value = 7;
Console.WriteLine(newList[0].Value);
newList[0].Value = 10;
Console.WriteLine(x.Value);
class MyInteger
{
public MyInteger(int value)
{
Value = value;
}
public int Value { get; set; }
}
ints are primitives, so you are not passing around a pointer,but the value it self.
Pointers are implicit in C#,so you can wrap ints in an object and pass that object around instead and you will be passing a pointer to the object.
You can't store value types in a .NET generic collection and access them by reference. What you could do is what Simon Whitehead suggested.
I see few solutions of this problem:
1) Create a class which will hold the integer (and possibly other values you might need)
2) Write "unsafe" code. .NET allows usage of pointers if you enable this for your project. This might even require creating custom collection classes.
3) Restructure your algorithm to not require references. E.g. save indexes of values you wish to change.
for example:
int x = 1;
int y = x;
y = 3;
Debug.WriteLine(x.ToString());
Is it any reference operator instead of "=" on line:3,
to make the x equal to 3 , if i assign y =3 .
I once wrote a prototype of a version of C# that had that feature; you could say:
int x = 123;
ref int y = ref x;
and now x and y would be aliases for the same variable.
We decided to not add the feature to the language; if you have a really awesome usage case I'd love to hear it.
You're not the first person to ask about this feature; see Can I use a reference inside a C# function like C++? for more details.
UPDATE: The feature will likely be in C# 7.
'int' is a value type and so copies the value on assignment, as you have discovered.
You could use pointers in the traditional C/C++ sense by using an 'unsafe' block but then the pointers are only usable inside that block which limits its use. If instead you want to access the value outside of an 'unsafe' block then you need to convert to using a reference instead.
Something like this...
var x = new Tuple<int>(1);
var y = x;
y.Item1 = 3;
This is not exactly what you're asking, but I thought it might be helpful. If you want a pointer alias inside a function, you can use the ref keyword like such:
public static void RefExample(ref int y)
{
y = 3;
}
main()
{
int x = 5;
RefExample(ref x);
Console.WriteLine(x); // prints 3
}
You can use pointers like in C
int x = 1;
unsafe
{
int* y = &x;
*y = 3;
}
Debug.WriteLine(x.ToString());
(Note you have to compile with the unsafe flag)
The only way to do this is to use "unsafe" code, and actually use pointers. Pointers cannot exist outside of unsafe code blocks in C#. You should then be able to use pointers the same way you do in C/C++
Check out this page for how to use "unsafe" code blocks.
I wanted to comment Eric Lippert's answer, but new users cannot comments posts. So, I think I have such usage.
Take a look at this code:
private void SetGridColumns(ref RegistryKey targetKey, List<ColInfo> cols)
{
string targetKeyName = Path.GetFileName(targetKey.Name);
m_grids.DeleteSubKeyTree(targetKeyName, false);
targetKey.Close();
targetKey = m_grids.CreateSubKey(targetKeyName);
//...
}
public void SetColumns(List<ColInfo> cols, bool youth)
{
RegistryKey key = youth ? m_youthGrid : m_mainGrid;
SetGridColumns(ref key, cols);
}
It should work like that:
In SetColumns I call SetGridColumns with key depending on "youth" param. I would like my key to be first deleted and then recreated. m_mainGrid is of course member of a class.
In this case, key is indeed deleted and recreated. But recreated is only "targetKey" in SetGridColumns, not my m_mainGrid.
So, the only thing I can do here is to make usage of pointers which is not preferred way in C#.
If I could only do:
ref RegistryKey key = youth ? m_youthGrid : m_mainGrid;
everything should work fine.
From a method, I can pass a struct which contains an array of integers, and change the values in the array. I am not sure I understand fully why I can do this. Can someone please explain why I can change the values stored in the int[]?
private void DoIt(){
SearchInfo a = new SearchInfo();
a.Index = 1;
a.Map = new int[] { 1 };
SearchInfo b = new SearchInfo();
b.Index = 1;
b.Map = new int[] { 1 };
ModifyA(a);
ModifyB(ref b);
Debug.Assert(a.Index == 1);
Debug.Assert(a.Map[0] == 1, "why did this change?");
Debug.Assert(b.Index == 99);
Debug.Assert(b.Map[0] == 99);
}
void ModifyA(SearchInfo a) {
a.Index = 99;
a.Map[0] = 99;
}
void ModifyB(ref SearchInfo b) {
b.Index = 99;
b.Map[0] = 99;
}
struct SearchInfo {
public int[] Map;
public int Index;
}
In C#, references are passed by value. An array is not copied when passed to method or when stored in an instance of another class. - a reference to the array is passed. This means a method which recieves a reference to an array (either directly or as part of another object) can modify the elements of that array.
Unlike languages like C++, you cannot declare "immutable" arrays in C# - you can however uses classes like List which have readonly wrappers available to prevent modification to the collection.
From a method, I can pass a struct which contains an array of integers, and change the values in the array. I am not sure I understand fully why I can do this.
An array is defined as a collection of variables.
Variables, by definition, can be changed. That is why we call them "variables".
Therefore when you pass an array, you can change the contents; the contents of an array are variables.
Why can I change a struct’s int[] property without specifying “ref”?
Remember, as we discussed before in a different question, you use ref to make an alias to a variable. That is what "ref" is for -- making aliases to variables. (It is unfortunate that the keyword is the confusing "ref" -- it probably would have been more clear to make it "alias".)
From MSDN:
Do not return an internal instance of an array. This allows calling code to change the array. The following example demonstrates how the array badChars can be changed by any code that accesses the Path property even though the property does not implement the set accessor.
using System;
using System.Collections;
public class ExampleClass
{
public sealed class Path
{
private Path(){}
private static char[] badChars = {'\"', '<', '>'};
public static char[] GetInvalidPathChars()
{
return badChars;
}
}
public static void Main()
{
// The following code displays the elements of the
// array as expected.
foreach(char c in Path.GetInvalidPathChars())
{
Console.Write(c);
}
Console.WriteLine();
// The following code sets all the values to A.
Path.GetInvalidPathChars()[0] = 'A';
Path.GetInvalidPathChars()[1] = 'A';
Path.GetInvalidPathChars()[2] = 'A';
// The following code displays the elements of the array to the
// console. Note that the values have changed.
foreach(char c in Path.GetInvalidPathChars())
{
Console.Write(c);
}
}
}
You cannot correct the problem in the preceding example by making the badChars array readonly (ReadOnly in Visual Basic). You can clone the badChars array and return the copy, but this has significant performance implications.
Although your SearchInfo struct is a value type, the .Map field is holding a reference, because Array is a reference type. Think of this reference as the address pointing to the memory location where the array resides.
When you pass an instance of SearchInfo to a method, as you know, the SearchInfo gets copied. And the copy naturally contains the very same address pointing to the very same array.
In other words, copying the struct doesn't make a copy of the array, it just makes a copy of the pointer.
Well, it is passed by reference anyway, like all reference types in C#.
Neither C# nor CLR support constness, unfortunately, so the platform doesn't really know if you are allowed to change it or not. So, it has the reference, it may use it to change the value, and there's nothing to stop it from doing so.
You may see it as a language design bug, btw. It is unexpected for the user.