How to set fixed length to class attributes? - c#

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())
);
}

Related

Using implicit operator overloading

I created the following struct to keep track of all my network IDs I use for my game:
public struct NetworkId {
private static int _availibleId = 1;
private int _id;
public static implicit operator int(NetworkId i) {
if (i._id == 0) {
i._id = _availibleId++;
}
return i._id;
}
}
I initialize the ID at the moment someone tries to access it. But my problem now is, when I use the id like in the following example, the ID gets reassigned every time.
public class TestObject {
private NetworkId _id;
public NetworkId Id { get { return _id; } }
public void Create {
NetworkManager.SendPacket(new Packets.CreateObject(Id));
}
}
I can't wrap my head around what is happening here. Thank you for your help!
Does it need to be a struct? With class semantics do this:
public class NetworkId
{
private static int _availibleId = 1;
public int Id { get; } = _availibleId++;
public static implicit operator int(NetworkId i)
{
return i.Id;
}
}
void Test() {
int A = new NetworkId(); //A=1
int B = new NetworkId(); //B=2
}

A class to help access a chunk of memory

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);
}

Why i can't modify these values in an object?

I have a problem, if i want to edit a value into an object and call it again, i get the old value instead of the new one.
Here is my Function to get the Class:
public static Clan GetClanByID(int Index)
{
foreach (Clan Clan in Clans)
{
if (Clan.ID == Index)
{
return Clan;
}
}
return new Clan()
{
ID = -1,
Name = "NULL",
IconID = -1
};
}
Here is my function to update the Value:
public static void ChangeAnnouncement(int ClanID, int Mode, string Text)
{
if (ClanID != -1)
{
Clan Clan = GetClanByID(ClanID);
if (Mode == 0)
{
Clan.Description = Text;
}
else if (Mode == 1)
{
Clan.News = Text;
}
}
}
And here is the class:
public class Clan
{
public int ID;
public int LeaderID;
public int Extension;
public int CreationDate;
public long EXP;
public long IconID;
public string Name;
public string News;
public string Description;
public List<ClanWars> ClanWars;
public List<ClanUsers> Users;
public List<ClanCoMasters> CoMasters;
public List<ClanPendingUsers> PendingUsers;
public LeaderInformations LeaderInformations;
}
Example: The old value was "123", than i call the function ChangeAnnouncement, and set the value to "1234567890", after that i get the value using GetClanByID(ID).Description, but i will still get the old value ("123")
I Hope you can help me.
You're returning a new Clan every time. You forgot adding the newly created clan to Clans.

Protobuf-Net always deserializes an empty list

The following code shows how I am trying to serialize/deserialze a List using Protobuf-Net. Method getNewItem() returns an object of ItemsStore, which is added to the List.
// Create an empty list
private ItemsStoreList text;
// Add some elements to the list
lock (text.SyncRoot)
{
text.AddItem(getNewItem());
text.AddItem(getNewItem());
text.AddItem(getNewItem());
}
// Serialize
var file = File.Create("testfile.bin");
Serializer.Serialize<ItemsStoreList>(file, text);
// Deserialize
ItemsStoreList textNew = Serializer.Deserialize<ItemsStoreList>(file);
After I run this code, the list contained in object textNew is always empty. Object textNew is instantiated from class ItemsStoreList, which is shown below:
[ProtoContract]
public class ItemsStoreList
{
[ProtoMember(1)]
private List<ItemsStore> m_listData;
private readonly object m_SyncRoot = new object();
public ItemsStoreList()
{
m_listData = new List<ItemsStore>();
}
public void AddItem(ItemsStore item)
{
m_listData.Add(item);
}
public object SyncRoot
{
get { return this.m_SyncRoot; }
}
public int Count
{
get { return m_listData.Count; }
}
public ItemsStore getItem(int idx)
{
return (ItemsStore)m_listData[idx];
}
public void Clear()
{
m_listData.Clear();
}
}
[ProtoContract]
public class ItemsStore
{
[ProtoMember(1)]
public myStruct m_Text;
[ProtoMember(2)]
public ulong m_Time;
public ItemsStore(myStruct newText, ulong newTime)
{
m_Text = newText;
m_Time = newTime;
}
public myStruct Text
{
get { return m_Text; }
}
public ulong Time
{
get { return m_Time; }
}
}
[ProtoContract]
public struct myStruct
{
[ProtoMember(1)]
public uint var1;
[ProtoMember(2)]
public byte var2;
[ProtoMember(3)]
public byte[] var3;
[ProtoMember(4)]
public string var4;
}
The first thing I note is that you have not rewound the stream; adding this (between serialize and deserialize) changes the behaviour:
file.Position = 0;
We now get an exception relating to the ItemsStore constructor, so we can instruct protobuf-net to ignore that constructor completely:
[ProtoContract(SkipConstructor = true)]
public class ItemsStore
Now we get 3 items back:
System.Console.WriteLine(textNew.Count);
which outputs:
3
Further probing shows that it is most likely fetching the other data too:
for (int i = 0; i < textNew.Count; i++)
{
var item = textNew.getItem(i);
System.Console.WriteLine(item.m_Text.var1);
System.Console.WriteLine(item.m_Time);
}
I will, however, add the obligatory warning about mutable structs and public fields.

C# How to use properties

A simple program using properties to encapsulate.. Farmer has field snumberofCows andfeedMultiplier,
and write to console BagsOfFeed= numberofCows* feedMultiplier
namespace numberOfCows
{
class Farmer
{
private int bagsOfFeed;
//public const int FeedMultiplier = 30;
private int numberOfCows;
private int feedMultiplier;
//private int bagsOfFeed;
public Farmer(int numberOfCows, int feedMultiplie)
{
feedMultiplier = feedMultiplie;
//this.feedMultiplier = feedMultiplie;
NumberOfCows = numberOfCows;
//this.numberOfCows = numberOfCows;
}
public int FeedMultiplier { get { return feedMultiplier; } }
public int NumberOfCows
{
get
{
return numberOfCows;
}
set
{
numberOfCows = value;
//BagsOfFeed = numberOfCows * FeedMultiplier;
}
}
//READ ONLY PROPERTY
public int BagsOfFeed {
get { return bagsOfFeed; }
set { bagsOfFeed = NumberOfCows * FeedMultiplier; }
}
}
}
When call farmer = new Farmer( 15,30 ); Console.WriteLine("I need {0} bags of feed for {1} cows",farmer.BagsOfFeed, farmer.NumberOfCows); returns 0 BagsOfFeed...So I don't know where i goes wrong..[I thought properties is used to retrieve values which is to read sth out...also,,when should i use private set..]
The set method for BagsOfFeed is never called since you never do BagsOfFeed = something;, so the calculation is never done. You should probably have the calculation in the get method, and remove the field for it. Your class also has other fields that don't need to exist. For example, with the FeedMultiplier property, you can use private set; (this is called an auto-property) instead of having just a get with a backing field. It could be rewritten as:
class Farmer
{
public Farmer(int numberOfCows, int feedMultiplier)
{
this.FeedMultiplier = feedMultiplier;
this.NumberOfCows = numberOfCows;
}
public int FeedMultiplier { get; private set; }
public int NumberOfCows { get; set; }
public int BagsOfFeed {
get { return NumberOfCows * FeedMultiplier; }
}
}
This shows the correct result in your example:
I need 450 bags of feed for 15 cows
BagsOfFeed setter is never called (and shouldn't be, as it's calculated based of values of other properties). This property should look like that:
//READ ONLY PROPERTY
public int BagsOfFeed {
get { return NumberOfCows * FeedMultiplier; }
}
With that, private int bagsOfFeed; can be removed as it's unnecessary.

Categories