i have an array and want to create two classes that contains the reference of this array. When i change value of an element in array, i want to see the change in classes. The reason why i want to do that is i have a array of something and i have many classes that should contain or reach this array. How can i do that?
In C, i put the pointer of the array in existing structs and solve the problem but how can i do that in C#? There is no array pointer afaik.
int CommonArray[2] = {1, 2};
struct
{
int a;
int *CommonArray;
}S1;
struct
{
int b;
int *CommonArray;
}S2;
S1.CommonArray = &CommonArray[0];
S2.CommonArray = &CommonArray[0];
Thank you.
All arrays are reference types in C#, even if the element type of the array is a value type. So this will be fine:
public class Foo {
private readonly int[] array;
public Foo(int[] array) {
this.array = array;
}
// Code which uses the array
}
// This is just a copy of Foo. You could also demonstrate this by
// creating two separate instances of Foo which happen to refer to the same array
public class Bar {
private readonly int[] array;
public Bar(int[] array) {
this.array = array;
}
// Code which uses the array
}
...
int[] array = { 10, 20 };
Foo foo = new Foo(array);
Bar bar = new Bar(array);
// Any changes to the contents of array will be "seen" via the array
// references in foo and bar
Related
public class TurnStatus{
public int[,] stonesStatus;
public bool[,] isHacked;
public bool[,] isTrapSet;
public TurnStatus(int[,] _stonesStatus, bool[,] _isHacked, bool[,] _isTrapSet)
{
stonesStatus = _stonesStatus;
isHacked = _isHacked;
isTrapSet = _isTrapSet;
}
}
public class TestClass : MonoBehaviour{
public int[,] currentStoneStatus = new int[10,10];
public bool[,] currentIsHacked = new bool[10, 10];
public bool[,] currentIsTrapSet = new bool[10, 10];
List<TurnStatus> TurnStatusList = new List<TurnStatus>();
void RecordTurnStatus()
{
TurnStatusList.Add(new TurnStatus(currentStoneStatus, currentIsHacked, currentIsTrapSet));
}
}
The code is as above.
After changing the values of currentStoneStatus, currentIsHacked, and currentTrapSet, the current three variables are stored and recorded in TurnStatusList as TurnStatus class variables through the RecordTurnStatus function.
The problem here, however, is that after calling the RecordTurnStatus function and recording the current state, all of the TurnStatus variables in the list are overwritten with the most recently stored ones.
For example, if you save A, B, and C in turn in the list, the contents of the list become {C, C, C}.
I kept reviewing it, but I couldn't figure out the problem.
I want your help.
This is because arrays are reference types, all the objects are pointing to the same arrays in the memory.
You should copy/clone the array, for example:
stonesStatus = _stonesStatus.Clone() as int[,];
How I do it currently:
class Foo
{
public int[] A { get { return (int[])a.Clone(); } }
private int[] a;
}
I think it's bad because it creates a clone and casts whenever I access it. I know I can work around it by introducing an additional variable like this
var foo = new Foo();
// as soon as you have to access foo.A do this
int[] fooA = foo.A;
// use fooA instead of foo.A from now on
but still it just looks bad.
I also dislike the java way of encapsulating
int get(int index) { return a[index]; }
because I dont get the advantages of using an array.
Is there any better way to do this?
edit: I want an array of encapsulated variables. The problem is that
public int[] A { get; private set; }
is not an array of encapsulated variables because I can modify elements of the array from outside of the class.
edit: It should also work with multidimensional arrays
Arrays implement IReadOnlyList<T> which exposes all of the relevant information you want (an iterator, an indexer, count, etc.) without exposing any of the mutable functionality of the array.
class Foo
{
public IReadOnlyList<int> A { get { return a; } }
private int[] a;
}
alternatively, you could use an iterator/generator to return the items as requested:
class Foo
{
public IEnumerable<int> A
{
get
{
foreach (int i in a)
yield return i;
}
}
private int[] a;
}
... then iterate over them normally or use LINQ to get them as a new array or other type of collection:
int[] arr = foo.A.ToArray();
Why not expose A as a implementation of IReadOnlyList
class Foo
{
public IReadOnlyList<int> A { get { return a; } }
private int[] a;
}
This allows you to return the Array as a collection where they can use the index but cannot change the contents of the array itself.
sounds like you need an indexer
...
public int this[int i]{
get{return a[i];}
set{a[i] = value;}
}
....
https://msdn.microsoft.com/en-us/library/6x16t2tx.aspx
So I have a array of class Piece called board.
There are some sub classes of piece such as Bishop and Knight and Rook ect...
The array looks like this:
Piece[,] board = new Piece[8,8];
board[0,0] = new Bishop(constructor stuff);
board[0,1] = new Rook(constructor stuff);
ect...
Each time I initialize a new instance of Bishop/Knight/Rook I want it to have it's own array so I can do
the following:
board[0,0].array[0] = ect...
How would I do that?
Add the array to the Piece class. All the subclasses will get access to it.
class Piece
{
public int[] array = new int[100]; // or whatever
// rest of class definition
}
Your Piece class would need to have a field or property for the array defined within it.
public abstract class Piece
{
public Something[] array = new Something[ARRAY_SIZE];
...
}
Do consider though whether this is actually a good design.
Add a variable to the classes called array which is an array?
Ex.
public class Bishop : Piece
{
// ...
public T[] array;
public Bishop()
: base()
{
// Initialize array
}
}
Where T is the type of the array.
You could make the class generic in case the array type might differ.
public class Bishop<T> : Piece
Then initialize it like:
board[0,0] = new Bishop<int>(); // array is int[]
I'd suggest you actually learning the basics of the language.
Say I have this C# class
public class MyClass {
int a;
int[] b = new int[6];
}
Now say I discover this class using reflection and while looking at the fields I find that one of them is of type Array (ie: b)
foreach( FieldInfo fieldinfo in classType.GetFields() )
{
if( fieldInfo.FieldType.IsArray )
{
int arraySize = ?;
...
}
}
I know it's not guaranteed that the array has a field initializer that creates the array but if it does I would like to know the size of the array created by the field initializer.
Is there a way to call the field initializer ?
If there was I would do something like this:
Array initValue = call field initializer() as Array;
int arraySize = initValue.Length;
The only was I found is to create an instance of the whole class but I would rather not do it like this as it's overkill...
Well, you can't.
The following code:
public class Test
{
public int[] test = new int[5];
public Test()
{
Console.Read();
}
}
will be compiled as:
public class Program
{
public int[] test;
public Program()
{
// Fields initializers are inserted at the beginning
// of the class constructor
this.test = new int[5];
// Calling base constructor
base.ctor();
// Executing derived class constructor instructions
Console.Read();
}
}
So, until you create an instance of the type, there is no way to know about the array size.
I dont think you have an option but to create an instance of the class as it doesnt exist until you do that.
I have a dummy class where I am testing arrays. I've noticed that when I want to dynamically allocate size of array at runtime, fields that indicate this size have to be static. I know I should probably use collections for this kind of code, but I'm more interested why do these fields have to be static? Is there any particular reason behind this?
class Foo
{
private static int x;
private static int y;
private int[,] bar = new int[ x, y ];
public Foo( int a, int b )
{
x = a;
y = b;
}
}
They don't really have to be static - it's just that you can't refer to other instance variables within instance variable initializers. In other words, it's a bit like this:
class Foo
{
private int x;
private int y = x; // Invalid
}
From section 10.5.5.2 of the C# 3 spec:
A variable initializer for an instance
field cannot reference the instance
being created. Thus, it is a
compile-time error to reference this
in a variable initializer, as it is a
compile-time error for a variable
initializer to reference any instance
member through a simple-name.
I suspect you really want something like this:
class Foo
{
private int x;
private int y;
private int[,] bar;
public Foo( int a, int b )
{
x = a;
y = b;
bar = new int[x, y];
}
}
Of course you don't really need x and y at all - they're just convenient to keep each dimension of the array. You could also use bar.GetLength(0) and bar.GetLength(1) to get the two lengths, but that's not terribly pleasant.
You might want to rename x and y to width and height though, or something similar :)
The example shown of 'Foo will never have the array 'bar be anything but an an array of size [0,0] : it's instantiation occurs before you call the class constructor.
Try this :
public class Foo2
{
private int[,] bar;
public Foo2(int a, int b)
{
bar = new int[a,b];
}
}
That will give you an array of size [a,b] without use of 'static.