I need a class to help me access a chunk of memory
So far I have this
class ABSet
{
private byte[] _raw;
public ABSet(byte[] RawData)
{
_raw=RawData;
}
public double A
{
get
{
return BitConverter.ToDouble(_raw, 2);
}
}
public double B
{
get
{
return BitConverter.ToDouble(_raw, 10);
}
}
}
Now I would like to do something like this
class ABSetCollection
{
private byte[] _raw;
public ABSetCollcetion(byte[] RawData)
{
_raw=RawData;
}
public ABSet this[int index]
{
get
{
// This Part Is What I Want To Figure Out
}
}
}
I know I could put return new ABSet(_raw); but I feel like there must be a solution that requires less dynamic allocation.
P.S. The reason I want to use properties is because I am binding to them in my GUI
Rather than just accepting an array of bytes, change it so you get an offset too. Then you'll be able to get that to work.
class ABSet
{
public const int ABSetSize = 20; // or whatever the size
private readonly byte[] _data;
private readonly int _offset;
public ABSet(byte[] data, int offset = 0)
{
_data = data;
_offset = offset;
}
const int AOffset = 2;
public double A => BitConverter.ToDouble(_data, _offset + AOffset);
const int BOffset = 10;
public double B => BitConverter.ToDouble(_data, _offset + BOffset);
}
class ABSetCollection
{
private readonly byte[] _data;
private readonly int _offset;
public ABSetCollection(byte[] data, int offset = 0)
{
_data = data;
_offset = offset;
}
public ABSet this[int index] => new ABSet(_data, _offset + index * ABSet.ABSetSize);
}
Related
I am currently doing a project on B+ trees. I want to set my records with fix length attributes such that each record object will be of the same size (bytes) but I am not sure how to go about doing it.
Below is my code for the Record class.
public struct Record
{
private string tConst;
private double averageRating;
private int numVotes;
public Record(string tConst, double averageRating, int numVotes)
{
this.tConst = tConst;
this.averageRating = averageRating;
this.numVotes = numVotes;
}
public string getTConst()
{
return this.tConst;
}
public double getAverageRating()
{
return this.averageRating;
}
public int getNumVotes()
{
return this.numVotes;
}
public int getBytes()
{
return (
System.Text.ASCIIEncoding.ASCII.GetByteCount(this.tConst) +
System.Text.ASCIIEncoding.ASCII.GetByteCount(this.averageRating.ToString()) +
System.Text.ASCIIEncoding.ASCII.GetByteCount(this.numVotes.ToString())
);
}
I have two classes which are close to the same, except for one variable type.The following example should demonstrate the problem.
class Customer
{
byte Reputation;
const byte MaximumReputation = 255;
int Data;
string MoreData;
Briefcase EvenMoreData;
public Customer(byte reputation, int data, string moreData, Briefcase evenMoreData)
{
Reputation = reputation;
Data = data;
MoreData = moreData;
EvenMoreData = evenMoreData;
}
public float Level()
{
return Reputation / MaximumReputation;
}
public string Information()
{
return Data.ToString() + ", " + MoreData + EvenMoreData.Id;
}
}
class CustomerDeluxe
{
ushort Reputation;
const byte MaximumReputation = 255;
int Data;
string MoreData;
Briefcase EvenMoreData;
public CustomerDeluxe(ushort reputation, int data, string moreData, Briefcase evenMoreData)
{
Reputation = reputation;
Data = data;
MoreData = moreData;
EvenMoreData = evenMoreData;
}
public float Level()
{
return Reputation / MaximumReputation;
}
public string Information()
{
return Data.ToString() + ", " + MoreData + EvenMoreData.Id;
}
}
Since Customers reputation won't exceed 255, I can store in a byte. In my application this field is a large array. That's why I would like to choose the smallest type possible. But there has to be another class for the few cases where the field can exceed a byte.
How can I "merge" these two classes?
Use generics:
public class BaseCustomer<TRep>
{
protected TRep Reputation;
}
public class CustomerDeluxe : BaseCustomer<ushort>
{
}
public class Customer : BaseCustomer<byte>
{
}
With generics, you are basically saying: "I am not sure what the type of TRep is but it will be manifested." A generic is said to be open when it is like above in BaseCustomer<TRep>. We will need to close it before we can use it. When we inherited it, then wevcloseed it with a specific type: in one instance we specified it to be ushort, in another we specified it to be byte.
And with some refactoring you can push most of the code to the BaseCustomer<T>:
public abstract class BaseCustomer<TRep>
{
protected TRep Reputation;
protected const byte MaximumReputation = 255;
int Data;
string MoreData;
Briefcase EvenMoreData;
public BaseCustomer(TRep reputation, int data, string moreData, Briefcase evenMoreData)
{
Reputation = reputation;
Data = data;
MoreData = moreData;
EvenMoreData = evenMoreData;
}
public abstract float Level();
public string Information()
{
return Data.ToString() + ", " + MoreData + EvenMoreData.Id;
}
}
public class CustomerDeluxe : BaseCustomer<ushort>
{
public CustomerDeluxe(ushort reputation, int data, string moreData, Briefcase evenMoreData)
: base(reputation, data, moreData, evenMoreData)
{
}
public override float Level()
{
return Reputation / MaximumReputation;
}
}
public class Customer : BaseCustomer<byte>
{
public Customer(byte reputation, int data, string moreData, Briefcase evenMoreData)
: base(reputation, data, moreData, evenMoreData)
{
}
public override float Level()
{
return Reputation / MaximumReputation;
}
}
class CustomerDeluxe : CustomerBase
{
ushort Reputation;
public override ushort GetReputation()
{
return Reputation;
}
}
class Customer : CustomerBase
{
byte Reputation;
public override ushort GetReputation()
{
return Reputation;
}
}
abstract class CustomerBase
{
const byte MaximumReputation = 255;
public abstract ushort GetReputation();
public float Level()
{
return GetReputation()/MaximumReputation;
}
}
I have a serializable class named DataSource:
namespace GraphLib
{
public struct cPoint
{
public float x;
public float y;
}
[Serializable]
public class DataSource
{
public delegate String OnDrawXAxisLabelEvent(DataSource src, int idx);
public delegate String OnDrawYAxisLabelEvent(DataSource src, float value);
public OnDrawXAxisLabelEvent OnRenderXAxisLabel = null;
public OnDrawYAxisLabelEvent OnRenderYAxisLabel = null;
private cPoint[] samples = null;
private int length = 0;
private String name = String.Empty;
private int downSample = 1;
private Color color = Color.Black;
public float VisibleDataRange_X = 0;
public float DY = 0;
public float YD0 = -200;
public float YD1 = 200;
public float Cur_YD0 = -200;
public float Cur_YD1 = 200;
public float grid_distance_y = 200; // grid distance in units ( draw a horizontal line every 200 units )
public float off_Y = 0;
public float grid_off_y = 0;
public bool yFlip = true;
public bool Active = true;
private bool YAutoScaleGraph = false;
private bool XAutoScaleGraph = false;
public float XAutoScaleOffset = 100;
public float CurGraphHeight = 1.0f;
public float CurGraphWidth = 1.0f;
public float InitialGraphHeight = 0;
public float InitialGraphWidth = 0;
public bool AutoScaleY
{
get
{
return YAutoScaleGraph;
}
set
{
YAutoScaleGraph = value;
}
}
public bool AutoScaleX
{
get
{
return XAutoScaleGraph;
}
set
{
XAutoScaleGraph = value;
}
}
public cPoint[] Samples
{
get
{
return samples;
}
set
{
samples = value;
length = samples.Length;
}
}
public float XMin
{
get
{
float x_min = float.MaxValue;
if (samples.Length > 0)
{
foreach (cPoint p in samples)
{
if (p.x < x_min) x_min=p.x;
}
}
return x_min;
}
}
public float XMax
{
get
{
float x_max = float.MinValue;
if (samples.Length > 0)
{
foreach (cPoint p in samples)
{
if (p.x > x_max) x_max = p.x;
}
}
return x_max;
}
}
public float YMin
{
get
{
float y_min = float.MaxValue;
if (samples.Length > 0)
{
foreach (cPoint p in samples)
{
if (p.y < y_min) y_min = p.y;
}
}
return y_min;
}
}
public float YMax
{
get
{
float y_max = float.MinValue;
if (samples.Length > 0)
{
foreach (cPoint p in samples)
{
if (p.y > y_max) y_max = p.y;
}
}
return y_max;
}
}
public void SetDisplayRangeY(float y_start, float y_end)
{
YD0 = y_start;
YD1 = y_end;
}
public void SetGridDistanceY( float grid_dist_y_units)
{
grid_distance_y = grid_dist_y_units;
}
public void SetGridOriginY( float off_y)
{
grid_off_y = off_y;
}
[Category("Properties")] // Take this out, and you will soon have problems with serialization;
[DefaultValue(typeof(string), "")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public String Name
{
get { return name; }
set { name = value; }
}
[Category("Properties")] // Take this out, and you will soon have problems with serialization;
[DefaultValue(typeof(Color), "")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public Color GraphColor
{
get { return color; }
set { color = value; }
}
[Category("Properties")] // Take this out, and you will soon have problems with serialization;
[DefaultValue(typeof(int), "0")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int Length
{
get { return length; }
set
{
length = value;
if (length != 0)
{
samples = new cPoint[length];
}
else
{
// length is 0
if (samples != null)
{
samples = null;
}
}
}
}
[Category("Properties")] // Take this out, and you will soon have problems with serialization;
[DefaultValue(typeof(int), "1")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int Downsampling
{
get { return downSample; }
set { downSample = value; }
}
}
}
and i want to serialize it in a form like this:
public partial class Form1 : Form
{
public GraphLib.PlotterDisplayEx display;
private void serialize()
{
System.IO.Stream TestFileStream = System.IO.File.Create(#"C:\Users\Public\Documents\test.txt");
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter serializer = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
serializer.Serialize(TestFileStream, display.DataSources[0]);
TestFileStream.Close();
}
not that DataSource class that i want to serialize in Form1, is one of the attributes in GraphLib.PlotterDisplayEx class
but when i run the program it gives me the following error:
An unhandled exception of type 'System.Runtime.Serialization.SerializationException' occurred in mscorlib.dll
Additional information: Type 'KTK.Form1' in Assembly 'KTK, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.
UPDATE
I updated the code for DataSource class.now it's complete code guys.
You probably didn't show the complete code of the DataSource class. It directly or indirectly holds a reference to an object of type KTK.Form1.
This might be through an event to which the form is subscribed.
In this case you probably don't want to serialize it an should mark it as NonSerialized:
[field:NonSerialized]
public event ...;
Now that you updated the question. Change
public OnDrawXAxisLabelEvent OnRenderXAxisLabel = null;
public OnDrawYAxisLabelEvent OnRenderYAxisLabel = null;
to
[NonSerialized]
public OnDrawXAxisLabelEvent OnRenderXAxisLabel;
[NonSerialized]
public OnDrawYAxisLabelEvent OnRenderYAxisLabel;
The delegates may hold references to non-serializable classes.
I have a class something like this (This is a subset of the code)
public struct overlay
{
[FieldOffset(0)]
public Byte[] b;
[FieldOffset(0)]
public Int32[] i;
}
class MyClass
{
private overlay data; \\Initialised using data.b=new Byte[4096]
public Int32 site0 { set { data.i[0] = value; } get { return data.i[0]; } }
public Int32 site1 { set { data.i[1] = value; } get { return data.i[1]; } }
public String s
{
get { return System.Text.Encoding.ASCII.GetString(data.b, 8, 16).TrimEnd(' '); }
set { System.Text.Encoding.ASCII.GetBytes(value.PadRight(16)).CopyTo(data.b, 8); }
}
public Int32 site2 { set { data.i[5] = value; } get { return data.i[5]; } }
}
I currently access the site variables like this...
MyClass m=new MyClass();
m.site0=1;
m.site1=1;
m.site2=1;
I would like to access them like this..
MyClass m=new MyClass();
for (Int32 i=0; i<m.sites.Count; ++i)
m.sites[i]=1;
Can anyone suggest how I would do that?
You can't create indexer for field in your class. You must make your own class which will store the data and then you can make field of it's type.
class MyClass
{
public MyIndexerClass Sites;
public class MyIndexerClass
{
private byte[] data;
public MyIndexerClass()
{
this.data = new byte[0];
}
public MyIndexerClass(byte[] Data)
{
this.data = Data;
}
public byte this[int index]
{
get
{
return data[index];
}
set
{
data[index] = value;
}
}
}
public MyClass()
{
this.Sites = new MyIndexerClass();
}
public MyClass(byte[] data)
{
this.Sites = new MyIndexerClass(data);
}
}
If you want to use Count property and foreach on MyIndexerClass, you should implement IEnumerable and create your own Enumerator.
The indexer syntax in C# allows to do that and it would look something like this:
public byte this[int index] {
get { return data[index]; }
set { data[index] = value; }
}
This defines an indexer on the type. Usage is like
m[i] = 1;
However, many array and list constructs in .NET already have indexers so you could define a field/property sites e.g. of Type List<byte>.
I have a base class that does calculations on image sizes. I'm deriving a class from that and have predefined image sizes that will be used in my code. While what I have works, I have a strong feeling that I'm not doing it properly.
Ideally, I'd like to just pass DerviedClass.PreviewSize as the parameter to GetWidth without having to create an instance of it.
class Program
{
static void Main(string[] args)
{
ProfilePics d = new ProfilePics();
Guid UserId = Guid.NewGuid();
ProfilePics.Preview PreviewSize = new ProfilePics.Preview();
d.Save(UserId, PreviewSize);
}
}
class ProfilePicsBase
{
public interface ISize
{
int Width { get; }
int Height { get; }
}
public void Save(Guid UserId, ISize Size)
{
string PicPath = GetTempPath(UserId);
Media.ResizeImage(PicPath, Size.Width, Size.Height);
}
}
class ProfilePics : ProfilePicsBase
{
public class Preview : ISize
{
public int Width { get { return 200; } }
public int Height { get { return 160; } }
}
}
It seems to me that you want a more flexible implementation of ISize - having an implementation which always returns the same value seems fairly pointless. On the other hand, I can see that you want an easy way of getting the size that you always use for a preview. I would do it like this:
// Immutable implementation of ISize
public class FixedSize : ISize
{
public static readonly FixedSize Preview = new FixedSize(200, 160);
private readonly int width;
private readonly int height;
public int Width { get { return width; } }
public int Height { get { return height; } }
public FixedSize(int width, int height)
{
this.width = width;
this.height = height;
}
}
You could then write:
ProfilePics d = new ProfilePics();
Guid userId = Guid.NewGuid();
d.Save(userId, FixedSize.Preview);
This would reuse the same instance of FixedSize whenever you called it.
There are a few ways that you could do this, depending on your needs. I would look at doing a different interface, setup. Something like this.
public interface ISizedPics
{
int Width {get; }
int Height {get; }
void Save(Guid userId)
}
public class ProfilePics, iSizedPics
{
public int Width { get { return 200; } }
public int Height { get { return 160; } }
public void Save(Guid UserId)
{
//Do your save here
}
}
Then, with this done, you could actually work with it like this.
ISizedPics picInstance = new ProfilePics;
Guid myId = Guid.NewGuid();
picInstance.Save(myId);
This is just one way of doing it, I like this way, as you can easily create a factory class around this that helps you declare the instances as needed.