As described in the title I'm unsure what a particular feature is called when a struct is treated as an array. For example, Unity3D has the Color struct which has 4 public floats r,g,b,a and public float this[int index] { get; set; }. Is there a particular term for what this feature is called? I'm coming from Java and just starting to learn about C#, I tried to look up what this was but was only finding stuff regarding how to create an array of structs.
It is called an "indexer property"
Example:
public struct Color
{
public int R { get; }
public int G { get; }
public int B { get; }
public int this[int index]
{
get
{
switch(index)
{
case 0: return R;
case 1: return G;
case 2: return B;
}
throw new IndexOutOfRangeException();
}
}
}
(Note: not the real Color you use, just an example off my head)
A property like that is called indexer:
public struct Color
private float[] components;
public float this[int index] { //<-- indexer.
get {
if (components == null) {
components = new float[4];
}
return components[index];
}
set {
if (components == null) {
components = new float[4];
}
components[index] = value;
}
}
}
Apparently the developers of Unity3D sometimes wanted to access the Color as if it was an collection of values for ARGB (aka channels). They used the indexer operator in order to mimic that.
You can read more on indexer operators on MSDN here and here.
Related
I'm looking for an implementation of a three dimensional circular buffer in C# .NET that allows me to extract slices of the buffer.
I tried the multidimensional array but it doesn't allow me to get a specific slice of the buffer.
I also tried to implement a version using jagged array, but i have find some problems in understanding how to initialzie the matrix, and also in slice extraction.
Thanks for the help.
[EDIT 1]
The buffer will be used to store data from reltime sensors, it will be fixed in width height and the depth (time which be the circular part) will be defined by the user.
The slices i need will be a fixed size matrix (width and heigh with the data of a given time).
[EDIT 2]
The only implementation that i could implement that works. With the jagged array i'm still stuck at the declaration (i find it chaotic)
public class CircularBufferMatrix<T>
{
private readonly T[,,] _buffer;
public CircularBufferMatrix(int width, int height, int depth)
{
Width = width;
Height = height;
Depth = depth;
_buffer = new T[width, height, depth];
}
public T this[int x, int y, int z]
{
set { _buffer[x, y, z%Depth] = value; }
get { return _buffer[x, y, z%Depth]; }
}
#region Getters
public int Width { get; }
public int Height { get; }
public int Depth { get; }
#endregion
}
I would split these in two classes. You want something like a CircularBuffer class, which handles the reading and writing. The other could be an implementation of the 2D array you want to store. The reason of splitting these, is because you want to Read/write frames separately.
For example:
Circular buffer implementation:
public class CircularBuffer<T>
{
private T[] _buffer;
private int IncRollover(int value)
{
value++;
if (value >= _buffer.Length)
value = 0;
return value;
}
public CircularBuffer(int count)
{
_buffer = new T[count];
}
public bool Write(T element)
{
// if the writeindex (after increasing) equals the readindex, the buffer is full
var newWriteIndex = IncRollover(WriteIndex);
if (newWriteIndex == ReadIndex)
return false;
_buffer[WriteIndex] = element;
WriteIndex = newWriteIndex;
return true;
}
public bool TryRead(out T element)
{
if (ReadIndex == WriteIndex)
{
element = default(T);
return false;
}
element = _buffer[ReadIndex];
ReadIndex = IncRollover(ReadIndex);
return true;
}
public IEnumerable<T> ReadAll()
{
T element;
while (TryRead(out element))
yield return element;
}
public int ReadIndex { get; private set; }
public int WriteIndex { get; private set; }
}
This will take care of reading and writing induvidual 'frames'/slices. You can expand this class if you like to read on Index.
note: The write will return false if the buffer is full
This could be an implementation of the 2d buffers stored within the Circular buffer:
public class MyWhateverBuffer<T>
{
private CircularBuffer<T[,]> _buffer;
public int Width { get; private set; }
public int Height { get; private set; }
public int Depth { get; private set; }
public MyWhateverBuffer(int width, int height, int depth)
{
Width = width;
Height = height;
Depth = depth;
_buffer = new CircularBuffer<T[,]>(depth);
}
public T[,] New()
{
return new T[Width, Height];
}
public bool Add(T[,] buffer)
{
return _buffer.Write(buffer);
}
public bool TryRead(out T[,] buffer)
{
return _buffer.TryRead(out buffer);
}
public IEnumerable<T[,]> ReadAll()
{
return _buffer.ReadAll();
}
}
This class can be used like:
MyWhateverBuffer<double> myBuffer = new MyWhateverBuffer<double>(100, 100, 100);
var oneSlice = myBuffer.New();
oneSlice[10, 10] = 3.5;
oneSlice[50, 10] = 23.5;
oneSlice[10, 20] = 43.5;
myBuffer.Add(oneSlice);
var anotherSlice = myBuffer.New();
anotherSlice[10, 10] = 13.5;
anotherSlice[50, 10] = 23.5;
anotherSlice[10, 20] = 43.5;
var result = myBuffer.Add(anotherSlice);
if(!result)
{
// the buffer was full..
}
// Read the results from the buffer.
foreach(var slice in myBuffer.ReadAll())
{
Trace.WriteLine(slice[10, 10]);
}
You should always check if the buffer could be added. You don't want to lose info.
Side note:
The most profit gains with a Circular buffer is declaring the elements ones. Like big arrays will be reused every time.
If I understand your requirements correctly, you want a circular buffer consisting of items that are two dimensional arrays of data and the data from one item is never repeated in other items. C# doesn't have a cicular buffer type but you can always create one yourself:-
public class CircularBuffer <T> // make it generic
{
public class Iterator
{
public void MoveForward ();
public void MoveBackward ();
public T Item { get { } };
CicrcularBuffer <T> m_container;
LinkedListNode <T> m_current_item;
}
public void Add (T item);
public Iterator GetIterator ();
LinkedList<T> m_data;
}
Then create a class to contain your data:-
public class SensorData
{
// contains the two dimension data
}
And use it like:-
var buffer = new CircularBuffer <SensorData> ();
var iterator = buffer.GetIterator ();
var item = iterator.Item;
iterator.MoveForward ();
Obviously, there's a lot to be filled in but it should get you started.
I am creating a crossword puzzle generator and seem to have an issue with a simple variable assignment of co-ordinates in the grid system.
I have a very simple structure to hold discrete coordinate values as seen below. I have stripped encapsulation to make it easier to read.
public struct vec2
{
public int x, y;
public vec2(int x, int y)
{
this.x = x;
this.y = y;
}
}
This Vec2 Structure is maintained inside a class to hold word values
public struct WordClass
{
string svalue;
bool flag;
public vec2 position;
public WordClass(string sarg, bool barg)
{
this.svalue = sarg;
this.flag = barg;
position = new vec2(0,0);
}
public string StringVal
{
get { return svalue; }
}
public bool FlagVal
{
get { return flag; }
}
public void DisableWord()
{
if (this.flipflop == false)
{
this.flipflop = true;
}
}
public void SetPos(int xa, int ya)
{
this.position.x = xa;
this.position.y = ya;
}
}
This should basically maintain a list of permanent words with a flag for usage, and a variable position as the system calculates optimal locations for the word.
I have a dynamic linked list of words
List<WordClass> WordList = new List<WordClass>();
and to change the coordinates of a word in the wordlist
//Arbitrary values
WordList[0].SetPos(Position_X, Position_Y);
Now my issue is that when I try to use the position of the word, no matter what I set it too prior, it maintains a default value of 0, 0. I have been scratching my head while doing other functionality, and it's left me wondering if I'm missing something important.
Problem seems to be related to the fact that vec2 is a ValueObject and you're trying to change it. The problematic lines are concretely those two:
this.position.x = xa;
this.position.y = ya;
Why? Because vec2 is a a struct each time you read it you get a temporary copy, then modify that copy, then the copy is thrown away, while you're still reading the original, unmodified one. That's one reason why value objects should be immutable as much as possible, unless you've got a strong reason.
The first step should be to make a proper immutable vec2 structure:
public struct vec2
{
public int x { get; private set; }
public int y { get; private set; }
public vec2(int x, int y)
{
this.x = x;
this.y = y;
}
}
Once you've got that, you need to take care of the modification in the SetPos method. Since the structure is immutable you can no longer read it, but instead each time you need to change it you'll throw the current instance away and create a new one:
public void SetPos(int xa, int ya)
{
this.position = new vec2(xa, ya);
}
This creates a brand-new structure and assings it to the internal field, containing the new values. As this doesn't really attempts to modify the structure, but instead change the structure for a new one it won't be subject to the same subtle bug.
I have 2 structs in C language:
struct CSquare
{
char Side;
int Row;
int Col;
};
struct CSide
{
char m_Side;
char m_Blocks[3][3];
CSquare *m_Moves;
};
and C++ code:
int Count = 0;
int Flag = 0;
if (m_Down->m_Blocks[0][1] == *m_Down)
{
Count++;
Flag |= 2;
// type of m_Down is CSide
}
I'm trying to convert they to C#:
public class Square
{
public char Side { get; set; }
public int Row { get; set; }
public int Col { get; set; }
}
public class CubeSide
{
private char Side { get; set; }
private char[,] _block = new char[3, 3];
private Square[] moves;
public char[,] Block
{
get { return _block; }
set { _block = value; }
}
internal Square[] Moves
{
get { return moves; }
set { moves = value; }
}
}
But I don't know how to convert line:
if (m_Down->m_Blocks[0][1] == *m_Down)
to C#?
How can I convert this line to C#?
this line make no sense, i guess it's always evaluate to false.
What you can do is to set a breakpoint on that line and perform a quick watch, evaluate *m_Down to make sure there's no overload operator.
Then, evaluate the condition. Depending on your type of project, put some printf("inside the if")/printf("inside the else"), messagebox or write it in a file. If the condition is evaluate to true, print the value of m_Down->m_BLocks[0][1] and *m_Down...
Make sure you first understand the logic behind this line. Once you understand it, it will be easy to write it in c#
PS: in C#, use Byte instead of Char
By way of an intro, I'm creating a basic Quadtree engine for personal learning purposes. I'm wanting this engine to have the capability of working with many different types of shapes (at the moment I'm going with circles and squares) that will all move around in a window and perform some sort of action when collision occurs.
Here are my shape objects as I have them so far:
public class QShape {
public int x { get; set; }
public int y { get; set; }
public string colour { get; set; }
}
public class QCircle : QShape {
public int radius;
public QCircle(int theRadius, int theX, int theY, string theColour) {
this.radius = theRadius;
this.x = theX;
this.y = theY;
this.colour = theColour;
}
}
public class QSquare : QShape {
public int sideLength;
public QSquare(int theSideLength, int theX, int theY, string theColour) {
this.sideLength = theSideLength;
this.x = theX;
this.y = theY;
this.colour = theColour;
}
}
Now my question is, how do I create a generic list (List<T> QObjectList = new List<T>();) in C# so I can have one list containing all these various shapes that may have different properties (e.g., QCircle has the "radius" property while QSquare has the "sideLength" property)? An example of implementation would be helpful as well.
I just know that there is a stupidly obvious answer to this question but I'd appreciate any help anyway. I'm trying to get back into C#; it has obviously been a while...
You need to use downcasting
Store the objects in a list with the base class
List<QShape> shapes = new List<QShape>
You can then upcast the object safely if you know what it is e.g.
if(shapes[0] is QSquare)
{
QSquare square = (QSquare)shapes[0]
}
You can also implicitly downcast objects
QSquare square = new Square(5,0,0,"Blue");
QShape shape = square
For more information read the Upcasting and Downcasting sections here
You should implement an Interface. For example
public interface IHasLength
{
int Length;
}
Then in the implementation you can do
public class QSquare : QShape, IHasLength {
public int sideLength;
public QSquare(int theSideLength, int theX, int theY, string theColour) {
this.sideLength = theSideLength;
this.x = theX;
this.y = theY;
this.colour = theColour;
}
public int Length { get { return sideLength; } }
}
public class QCircle : QShape, IHasLength {
public int radius;
public QSquare(int theSideLength, int theX, int theY, string theColour) {
this.sideLength = theSideLength;
this.x = theX;
this.y = theY;
this.colour = theColour;
}
public int Length { get { return radius; } }
}
FInally, in your list:
List<IHasLength> shapesWithSomeLength = new List<IHasLength>();
Now your list can hold ANYTHING that implements IHasLength whether it's a QCircle, QShape, or even a QDuck if you want as long as it implements IHasLength.
Is this what you want?
public class QShape
{
protected QShape() { }
public int x { get; set; }
public int y { get; set; }
public string colour { get; set; }
}
public class QCircle : QShape
{
public int radius;
public QCircle(int theRadius, int theX, int theY, string theColour)
{
this.radius = theRadius;
this.x = theX;
this.y = theY;
this.colour = theColour;
}
}
public class QSquare : QShape
{
public int sideLength;
public QSquare(int theSideLength, int theX, int theY, string theColour)
{
this.sideLength = theSideLength;
this.x = theX;
this.y = theY;
this.colour = theColour;
}
}
class Program
{
static void Main(string[] args)
{
List<QShape> list = new List<QShape>();
list.Add(new QCircle(100, 50, 50, "Red"));
list.Add(new QCircle(100, 400, 400, "Red"));
list.Add(new QSquare(50, 300, 100, "Blue"));
foreach (var item in list.OfType<QCircle>())
{
item.radius += 10;
}
foreach (var item in list.OfType<QSquare>())
{
item.sideLength += 10;
}
}
}
You could store them in a List<QShape> but this would mean that you could not access type-specific properties.
Generally, you might approach this by providing a common interface in your base class, and overriding behaviour in subclasses. In this way, a common interface can hide a diverse bunch of behaviours. For instance a Grow method could hide the complexities of growing items of different shape and could be called without explicit knowlege of the shape upon which it is operating.
public abstract class QShape {
public abstract void Grow(int amt);
}
public class QSquare : QShape {
private int sideLength;
public override void Grow(int amt)
{
sideLength+=amt;
}
}
public class QCircle : QShape {
private int radius;
public override void Grow(int amt)
{
radius+=amt;
}
}
I feel like i'm missing something but...
List<QCircle> circleObjects = new List<QCircle>();
and
List<QSquare> squareObjects = new List<QSquare>();
will work perfectly well.
EDIT:
Ah, I didn't understand what was being asked.
Yes, as your QCircle and QSquare classes inherit from QShape, you can just do.
List<QShape> shapes= new List<QShape>();
It's worth noting that if you want to access the radius property of all the QCircle's in that list, then you are going to have to filter the list based on type.
You can use Ian Mercer's comment List<QShape>
And here's how you would fill it:
List<QShape> shapes = new List<QShape>();
QCircle circle = new QCircle();
shapes.Add(circle);
To unbox it:
QCircle circle = (QCircle) shapes[0];
If you need to call a method off the base class, no need to unbox, just use it.
Storing
You're already on the right track with your class definitions. What you have to do is make a List of the superclass (in this case, QShape), which will be able to hold all of your shapes.
Here's an example of how you would make it:
List<QShape> objects = new List<QShape>();
objects.add(new QCircle(...));
objects.add(new QSquare(...));
Accessing
The problem here is differentiating what is what once everything is in the list. That's done with the getType() and typeof() methods of C#. (Jon Skeet has an excellent answer about how to do this). Basically, it looks like this:
if(objects.get(some_position).getType() == typeof(QCircle))
QCircle circle = objects.get(some_position);
else if(/* like above with QSquare */)
QSquare square = objects.get(some_position);
After you do this, you can resume using your objects like normal. But if you try accessing them from the list, you can only use the methods and variables that QShape has, as every object put in the list will be cast to it.
public Class abstract Base<T>
{
public abstract List<T>GetList();
}
then do this
public class className:Base<ObjectName>
{
public override List<T>GetList()
{
//do work here
}
}
I have a 2d array of a class. The size of array is very large (around 3000*3000) and accessing the array with ordinary row and column method is taking very much time. For this purpose, I want to use pointers to access the array.
Following is my array code:
Class definition:
Class BoxData
{
Size _bound;
bool _isFilled=false;
Color _color=Colors.White;
public Size Bounds
{
get
{
return _bound;
}
set
{
_bound=value;
}
}
public bool IsFilled
{
get
{
return _isFilled;
}
set
{
_isFilled=value;
}
}
public Color FillColor
{
get
{
return _color;
}
set
{
_color=value;
}
}
}
Class used as array in application:
BoxData[,] boxData=new BoxData[3000,3000];
I want to access boxData with pointers.
Thanks
Try a jagged array instead of a multi dimensional one, they are faster in Microsoft's CLR implementation
BoxData[][] boxData=new BoxData[3000][];
for (int i=0; i<3000; i++)
boxData[i] = new BoxData[3000];
Maybe you could use a struct instead of a class for BoxData ?
Struct is a value type: as you declare your array, everything will be populated already.
You will not longer use a loop to create new BoxData() instances.
var x = new BoxData[3000,3000]; // Populated array of BoxData
Because of struct vs class restrictions, you will have to remove initializers this way...
struct BoxData
{
Size _bound;
bool _isFilled; // = false;
Color _color; // = Color.White;
public Size Bounds
{
get
{
return _bound;
}
set
{
_bound = value;
}
}
public bool IsFilled
{
get
{
return _isFilled;
}
set
{
_isFilled = value;
}
}
public Color FillColor
{
get
{
return _color;
}
set
{
_color = value;
}
}
}
...and initialize your default values using a loop will be much more faster.
for (int j = 0; j < 3000; j++)
for (int i = 0; i < 3000; i++)
x[i, j].FillColor = Color.White;