Saving a reference to a int - c#

Here is a much simplified version of what I am trying to do
static void Main(string[] args)
{
int test = 0;
int test2 = 0;
Test A = new Test(ref test);
Test B = new Test(ref test);
Test C = new Test(ref test2);
A.write(); //Writes 1 should write 1
B.write(); //Writes 1 should write 2
C.write(); //Writes 1 should write 1
Console.ReadLine();
}
class Test
{
int _a;
public Test(ref int a)
{
_a = a; //I loose the reference here
}
public void write()
{
var b = System.Threading.Interlocked.Increment(ref _a);
Console.WriteLine(b);
}
}
In my real code I have a int that will be incremented by many threads however where the threads a called it will not be easy to pass it the parameter that points it at the int(In the real code this is happening inside a IEnumerator). So a requirement is the reference must be made in the constructor. Also not all threads will be pointing at the same single base int so I can not use a global static int either. I know I can just box the int inside a class and pass the class around but I wanted to know if that is the correct way of doing something like this?
What I think could be the correct way:
static void Main(string[] args)
{
Holder holder = new Holder(0);
Holder holder2 = new Holder(0);
Test A = new Test(holder);
Test B = new Test(holder);
Test C = new Test(holder2);
A.write(); //Writes 1 should write 1
B.write(); //Writes 2 should write 2
C.write(); //Writes 1 should write 1
Console.ReadLine();
}
class Holder
{
public Holder(int i)
{
num = i;
}
public int num;
}
class Test
{
Holder _holder;
public Test(Holder holder)
{
_holder = holder;
}
public void write()
{
var b = System.Threading.Interlocked.Increment(ref _holder.num);
Console.WriteLine(b);
}
}
Is there a better way than this?

Basically, the answer is Yes, you need a class.
There is no concept of 'reference to int' that you can store as a field. In C# it is limited to parameters.
And while there is an unsafe way (pointer to int, int*) the complexities of dealing with the GC in that scenario make it impractical and inefficient.
So your second example looks OK.

You cannot store a reference to a variable, for precisely the reason that someone could do what you are doing: take a reference to a local variable, and then use that reference after the local variable's storage is reclaimed.
Your approach of making the variable into a field of a class is fine. An alternative way of doing the same thing is to make getter and setter delegates to the variable. If the delegates are closed over an outer local variable, that outer local will be hoisted to a field so that its lifetime is longer than that of the delegates.

It is not possible to store a reference as a field.
You need to hold the int in a class.

Related

C# List is adding incorrect members

I am trying to add a few different members to a list, but when the list is added to it contains copies of only the last member added:
private PotentialSolution tryFirstTrack(PotentialSolution ps, List<PotentialSolution> possibleTracks)
{
for (Track trytrack = Track.Empty + 1; trytrack < Track.MaxVal; trytrack++)
{
if (validMove(ps.nextSide, trytrack))
{
ps.SetCell(trytrack);
possibleTracks.Add(ps);
}
}
return tryNextTrack(ps, possibleTracks);
}
The PotentialSolution class looks like this:
public class PotentialSolution
{
public Track[,] board;
public Side nextSide;
public int h;
public int w;
static int cellsPerSide;
static bool testing;
static int minTracks;
.....
public void SetCell(Track t)
{
board[h, w] = t;
}
}
So we are trying to make several copies of the board which only differ by which 'track' is placed in the current cell.
If I have a breakpoint at possibleTracks.Add(ps) then I can see by inspecting ps that the required cell contents is changing each time, as required.
But when the code reaches the next line (or the return statement), the cell content is the same in each member of the list (it's the last one that was added).
What I am doing wrong here? I have tried using an ArrayList and also a basic array instead, but get the same result. It's acting as though the board member is decared as static, but it's not.
[edit]
In response to those who suggested making copies of ps, you are correct and I had tried this before - but only tried single-stepping after the change and didn't run the full program (this method is used hundreds of times). When running the full program, making copies of ps certainly makes a difference to the result (although it's still not correct). The problem now, and why I didn't stick with using the copies, is that an added test still shows the list to contain the same versions of ps, even though the debugger has shown 2 or 3 different tracks being deployed:
private PotentialSolution tryFirstTrack(PotentialSolution ps, List<PotentialSolution> possibleTracks)
{
for (Track trytrack = Track.Empty + 1; trytrack < Track.MaxVal; trytrack++)
{
if (validMove(ps.nextSide, trytrack))
{
PotentialSolution newps = new PotentialSolution(ps);
newps.SetCell(trytrack);
possibleTracks.Add(newps);
}
}
// temporary test, can be removed
if (possibleTracks.Count >= 2)
{
PotentialSolution ps1 = new PotentialSolution(possibleTracks.First());
PotentialSolution ps2 = new PotentialSolution(possibleTracks.Last());
if (ps1.GetCell() != ps2.GetCell())
{
// should always get here but never does
int foo = 1;
}
}
return tryNextTrack(ps, possibleTracks);
}
By the way, Track and nextSide are just enum integers, they will be 0-6, and the list will contain 0,1,2,or 3 members, never more.
You are adding references to the same object: ps in possibleTracks.Add(ps)
You could add a constructor to PotentialSolution duplicating the class:
public class PotentialSolution
{
public Track[,] board;
public Side nextSide;
public int h;
public int w;
static int cellsPerSide;
static bool testing;
static int minTracks;
//.....
public PotentialSolution()
{
}
public PotentialSolution(PotentialSolution ps)
{
board = ps.board;
nextSide = ps.nextSide;
h = ps.h;
w = ps.w;
}
//.....
Then use:
private PotentialSolution tryFirstTrack(PotentialSolution ps, List<PotentialSolution> possibleTracks)
{
for (Track trytrack = Track.Empty + 1; trytrack < Track.MaxVal; trytrack++)
{
if (validMove(ps.nextSide, trytrack))
{
ps.SetCell(trytrack);
possibleTracks.Add(new PotentialSolution(ps)); // duplicate object
}
}
return tryNextTrack(ps, possibleTracks);
}
This creates a new instance of the class each time it is added to the list.
Consider giving the PotentialSolution type value semantics by making it a struct and implementing a Clone method, or a constructor that takes another PotentialSolution as an argument. Also, to clone a 2D array of value types, call Object.Clone() and cast the result to T[,].
When making a copy of your PotentialSolution, you'll need to make sure your clone your board array, because, in your case, each PotentialSolution keeps its own representation of the state of the board.
I feel like the critical part you're missing is how to shallow clone a 2D array, which in general, is:
T[,] copy = (T[,])original.Clone();
WARNING: Clone creates a shallow copy of the array. For value-types this copies the values of each element, so for your int-like "Track" type it does what you want, but for other readers who may be using reference-types (like classes) it does not clone each object referred to by each element of the array. The elements of the new array are just object references, and will still refer to the same objects referred to by the elements of the original array. See the documentation.
Full example below that changes the middle cell of a 3x3 board from A to B.
using System;
using System.Linq;
public enum Track { A, B, C }
public enum Side { X, Y, Z }
public struct PotentialSolution
{
public Track[,] board;
public Side nextSide;
public int h;
public int w;
public void SetCell(Track t)
{
board[h, w] = t;
}
public PotentialSolution(Track[,] board, Side nextSide, int h, int w)
{
this.board = (Track[,])board.Clone();
this.nextSide = nextSide;
this.h = h;
this.w = w;
}
public PotentialSolution Clone()
{
return new PotentialSolution(board, nextSide, h, w);
}
// This `ToString` is provided for illustration only
public override string ToString()
{
var range0 = board.GetLength(0);
var range1 = board.GetLength(1);
var b = board;
return string.Join(",",
Enumerable.Range(0, range0)
.Select(x => Enumerable.Range(0, range1)
.Select(y => b[x, y]))
.Select(z => "[" + string.Join(",", z) + "]"));
}
}
class Program
{
static void Main(string[] args)
{
Track[,] someBoard = new Track[3, 3];
PotentialSolution ps1 = new PotentialSolution(someBoard, Side.X, 1, 1);
ps1.SetCell(Track.A);
PotentialSolution ps2 = ps1.Clone();
ps2.SetCell(Track.B);
Console.WriteLine(ps1);
Console.WriteLine(ps2);
}
}
I'm filling in the blanks liberally, so please excuse any assumptions I have made that differ from your actual situation, because I have done so only to make this example self-contained. My ToString implementation and its usage of System.Linq is not necessary; it's purely for the purposes of displaying the 2D array in my example.
You always call SetCell on the same ps object you received as a parameter then add the same instance to the possibleTracks list. The result is: possibleTrack contains ps n times and because it is the same instance you used in each cycle it will have the last change you applied via SetCell call.
Not sure what you wanted to achieve but it looks you need a modified copy of ps in each cycle for adding to possibleTrack list. Making PotentialSolution a struct instead of class could be enough? Structs are copied in such a way but may hit your performance if PotentialSolution is big.
The board member will still generate the same problem, because despite ps will be copied but the board inside it will contain same Track references. The trick can be applied to Track too, but the performance issues may raise more.
Just implement a Clone on PotentialSolution to have fully detached instances of it, then call ````SetCell``` on cloned instance and add that instance to the list.

How can i call upon only the return variable in a method?

I'm new and struggling with object orientated programming. I want to use only the return value in my third method 'tableinfo' however i don't know how to transfer only this value to the other methods, without running the first two methods again. All i want to do is transfer only the value that the user enters over to the third method and not have to put in the values two times each, this is the only way i know to get the value across and i would really appreciate if anyone could help me to just get the return value. This code is a tiny snippet of what i'm trying to do and it's purpose is not important, i just wanted to create an example to try and allow people to understand what i mean.
Thank you in advance!
class Program
{
static void Main(string[] args)
{
TableOrder TO = new TableOrder();
TO.TableNumber();
TO.NumberOfPartons();
TO.tableinfo();
}
}
class TableOrder
{
int tablenumber;
string inputtablenumber;
int numberAtTable;
string inputNumberAtTable;
public int TableNumber()
{
Console.Write("please enter the table number:");
inputtablenumber = Console.ReadLine();
tablenumber = int.Parse(inputtablenumber);
return tablenumber;
}
public int NumberOfPartons()
{
Console.Write("please enter how many people are seated: ");
inputNumberAtTable = Console.ReadLine();
numberAtTable = int.Parse(inputNumberAtTable);
return numberAtTable;
}
public void tableinfo()
{
int tablenum = TableNumber();
Console.Write(tablenumber + 1);
int patrons = NumberOfPartons();
Console.WriteLine(numberAtTable + 1);
}
}
It looks like you might be confused on the difference between methods, properties, and fields. Your function TableNumber() might be more accurately called AskUserForTableNumber() or GetTableNumberFromInput(). Something like that. You are also both setting a member field and returning the value. So there are a bunch of ways you could store and retrieve that value. If the member field tablenumber was marked as public, you could access it. Or in your main function you could do this:
int tablenum=TO.TableNumber();
and then reuse that value.
Another odd thing you are doing is storing the input string as a member field. If you don't need to reference that string again, then there's no reason for that to be a member of the TableOrder object, it could be a local variable to the function that is doing the input.
But it seems like you are trying to use TableOrder.TableNumber like a property. And that very well may be the right thing to do, but not in the way that you are doing it. Here is a (sort of fancy) way of doing something similar, which also uses a concept of lazy-loading...
class TableOrder
{
private int? _tablenumber;
public int TableNumber
{
get
{
return _tablenumber ?? (_tablenumber=GetTableNumberFromInput());
}
set
{
_tablenumber = value;
}
}
private static int GetTableNumberFromInput()
{
Console.Write("please enter the table number:");
string inputtablenumber = Console.ReadLine();
return int.Parse(inputtablenumber);
}
//(and so on for other member properties)
}
This way, the first time you try to access table number, it will ask the user for the value. Afterward, you will already have the value, so it will not ask again. Note that this type of approach is not really necessary, and is mainly useful for waiting to load a value until you need to use that value. Instead you could just do something like: TableOrder.TableNumber = GetTableNumberFromInput();
First of all, you can remove the calls in your main since the method tableinfo() will call them:
class Program
{
static void Main(string[] args)
{
TableOrder TO = new TableOrder();
TO.tableinfo();
}
}
Second, you want to use the class variables that you already declared,
The returned value of the two functions are stored inside those and you can output them with Write.
public void tableinfo()
{
tablenumber = TableNumber();
Console.Write(tablenumber + 1);
numberAtTable = NumberOfPartons();
Console.WriteLine(numberAtTable + 1);
}
In the scope of this function, the return values (return numberAtTable and return tablenumber) don't exist anymore, they are stored in whats left of the called functions.

Having an integer inside a method that increases by 1 everytime the method was called to a specific object of a lass

I have a 'Movie' class in my C# code that has an int[] ratings = new int[10]; as a field. I would like to place numbers in this empty array from my main program.
For that, I would need a method, that could point to the actual free index of the array to put the integer there, but the other integer that would point to the free index would be reset to 0 everytime the method is called. Thus, my question is, that how can I place an integer in my method that is increased everytime the method was called.
This is the method in the class:
public void Rate(int rating)
{
int x = 0;
ratings[x] = rating;
}
This is how I call it in the main program
Movie asd = new Movie(blabla...);
Rate.asd(1);
Rate.asd(1);
Rate.asd(1);
So I called it 3 times, and I would want the 'x' integer in the class's method to increase.
Thanks in advance.
First of all, you have an error in the code you have posted.
As I suppose rather than:
Movie asd = new Movie(blabla...);
Rate.asd(1);
Rate.asd(1);
Rate.asd(1);
you want to paste here:
Movie asd = new Movie(blabla...);
asd.Rate(1);
asd.Rate(1);
asd.Rate(1);
As C# does not allow to use static method variables (like i.e. C++ does) you have two options:
first, make x value (from Rate method) a Movie's class variable, so Rate method will "remember" the next index,
second (and better) rather than intiger array - if possible use any kind of list or queue (which can manage indexing for you).
The problem is that local variables are discarded when exiting a method.
class SomeClass
{
private int x = 42;
public void DoSometing(int y)
{
int a = y + 5;
x += a * a;
// a stops to exist here
}
}
Solution is to store the variable in the containing class as well
class SomeOtherClass
{
private int x = 42;
private int a = 0;
public void DoSomething(int y)
{
a = y + 5;
x += a * a;
}
}
Now SomeOtherClass remembers the value of a. That's basically the point of member variables a.k.a. fields - to store the state of the object.
More appropriate for your problem:
class ClassWithAnArrayAndCount
{
private int[] values = new int[10];
private int taken = 0;
public void Add(int value)
{
if (taken == 10)
throw new ArgumentOutOfRangeException(); // sorry, no more space
values[taken++] = value;
}
public int Taken { get { return taken; } }
}

How to validate two out parameters do not point to the same address?

I created a method that takes 2 out parameters. I noticed that it is possible for calling code to pass in the same variable for both parameters, but this method requires that these parameters be separate. I came up with what I think is the best way to validate that this is true, but I am unsure if it will work 100% of the time. Here is the code I came up with, with questions embedded.
private static void callTwoOuts()
{
int same = 0;
twoOuts(out same, out same);
Console.WriteLine(same); // "2"
}
private static void twoOuts(out int one, out int two)
{
unsafe
{
// Is the following line guaranteed atomic so that it will always work?
// Or could the GC move 'same' to a different address between statements?
fixed (int* oneAddr = &one, twoAddr = &two)
{
if (oneAddr == twoAddr)
{
throw new ArgumentException("one and two must be seperate variables!");
}
}
// Does this help?
GC.KeepAlive(one);
GC.KeepAlive(two);
}
one = 1;
two = 2;
// Assume more complicated code the requires one/two be seperate
}
I know that an easier way to solve this problem would simply be to use method-local variables and only copy to the out parameters at the end, but I am curious if there is an easy way to validate the addresses such that this is not required.
I'm not sure why you ever would want to know it, but here's a possible hack:
private static void AreSameParameter(out int one, out int two)
{
one = 1;
two = 1;
one = 2;
if (two == 2)
Console.WriteLine("Same");
else
Console.WriteLine("Different");
}
static void Main(string[] args)
{
int a;
int b;
AreSameParameter(out a, out a); // Same
AreSameParameter(out a, out b); // Different
Console.ReadLine();
}
Initially I have to set both variables to any value. Then setting one variable to a different value: if the other variable was also changed, then they both point to the same variable.

Interesting "params of ref" feature, any workarounds?

I wonder if there's any way something like this would be possible for value types...
public static class ExtensionMethods {
public static void SetTo(this Boolean source, params Boolean[] bools) {
for (int i = 0; i < bools.Length; i++) {
bools[i] = source;
}
}
}
then this would be possible:
Boolean a = true, b, c = true, d = true, e;
b.SetTo(a, c, d, e);
Of course, this does not work because the bools are a value type so they are passed into the function as a value, not as a reference.
Other than wrapping the value types into reference types (by creating another class), is there any way to pass a variable into function by the reference (ref) while using params modifier?
This is not possible. To explain why, first read my essay on why it is that we optimize deallocation of local variables of value type by putting them on the stack:
https://web.archive.org/web/20100224071314/http://blogs.msdn.com/ericlippert/archive/2009/05/04/the-stack-is-an-implementation-detail-part-two.aspx
Now that you understand that, it should be clear why you cannot store a "ref bool" in an array. If you could, then you could have an array which survives longer than the stack variable being referenced. We have two choices: either allow this, and produce programs which crash and die horribly if you get it wrong -- this is the choice made by the designers of C. Or, disallow it, and have a system which is less flexible but more safe. We chose the latter.
But let's think about this a little deeper. If what you want is to pass around "thing which allows me to set a variable", we have that. That's just a delegate:
static void DoStuff<T>(this T thing, params Action<T>[] actions)
{
foreach(var action in actions) action(thing);
}
...
bool b = whatever;
b.DoStuff(x=>{q = x;}, x=>{r = x;} );
Make sense?
There isn't really a way. You could do something like this:
public static void Main(string[] args)
{
BooleanWrapper a = true, b = true, c = true, d = true, e = new BooleanWrapper();
b.SetTo(a, c, d, e);
}
public static void SetTo(this BooleanWrapper sourceWrapper, params BooleanWrapper[] wrappers)
{
foreach (var w in wrappers)
w.Value = sourceWrapper.Value;
}
public class BooleanWrapper
{
public BooleanWrapper() { }
public BooleanWrapper(Boolean value)
{
Value = value;
}
public Boolean Value { get; set; }
public static implicit operator BooleanWrapper(Boolean value)
{
return new BooleanWrapper(value);
}
}
But then again how is that any better than just doing this:
public static void Main(string[] args)
{
Boolean[] bools = new Boolean[5];
bools.SetTo(bools[1]); // Note I changed the order of arguments. I think this makes more sense.
}
public static void SetTo(this Boolean[] bools, Boolean value)
{
for(int i = 0; i < bools.Length; i++)
bools[i] = value;
}
After all, an array is a sequence of variables. If you need something that behaves like a sequence of variables, use an array.
Unfortunately the community of Java, and now .NET, developers decided that less flexibility in the name of "safety" is the preferred solution, and to achieve the same result with less lines of code you have to opt for extraordinary complexity (all those class structures, delegates, etc.).
In Delphi I could simply do something like this:
var
a: integer; f: double; n: integer;
sscanf(fmtstr, valuestr, [#a, #f, #n]);
//<-- "sscanf" is a function I wrote myself that takes an open array of pointers.
In C# You would have to do:
int a; double f; int n;
object [] o = new object[];
sscanf(fmtstr, valuestr, ref o);
a = o[0];
f = o[1];
n = o[2];
That's 5 lines of code to do what I could do in 1 line of Delphi code. I think there is a formula somewhere that the likelihood of bugs in code increases geometrically with the number of lines of code; so if you have 20 lines of code you're code is 4 times more likely to have bugs than if you have 10.
Of course, you can decrease your # lines of code by using the delegate with all those weird angle brackets and strange syntax, but I would think that's also a haven for bugs.
Here is some interesting solution:
public delegate RecursionRefFunc<T> RecursionRefFunc<T>(ref T arg);
public static RecursionRefFunc<T> Boo<T>(ref T input)
{
Console.WriteLine(input); // Work in here
return Boo;
}
public static void Main(string[] args)
{
int x1 = 1, x2 = 2, x3 = 3, x4 = 4, x5 = 5;
Boo(ref x1)(ref x2)(ref x3)(ref x4)(ref x5);
}
// Output: //
// 1
// 2
// 3
// 4
// 5
Delegate can declare in recursion.
Return a function outside and call again.
And you will be killed by the code reviewer.
Advertisement OW<: CWKSC/MyLib_Csharp
This would not be possible even if bools were reference types. While a class is a reference type, the variable in the Boolean[] is still a value, it's just that the value is a reference. Assigning the value of the reference just changes the value of that particular variable. The concept of an array of ref variables doesn't make sense (as arrays are, by their nature, a series of values).

Categories

Resources