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>.
Related
How can I write the getter and setter expression for array property CoolerFanIsOn in the class CoolerSystem? I showed the similar desired expression for non-array property IsOn of Lamp class.
class CoolerFan{
bool isOn;
public bool IsOn {
get => isOn;
set {
isOn = value;
}
}
}
class CoolerSystem {
private CoolerFan[] = new CoolerFan[5];
private bool[] coolerFanIsOn = new Boolean[5];
// invalid code from now
public bool[] CoolerFanIsOn {
get => coolerFanIsOn[number];
set {
coolerFanIsOn[number] = value;
}
}
}
You can use indexer:
public class CoolerSystem
{
private bool[] _coolerFanIsOn = new Boolean[5];
public bool this[int index]
{
get => _coolerFanIsOn[index];
set => _coolerFanIsOn[index] = value;
}
}
Btw, the => are expression bodied properties which were new in C#6. If you can't use (setter was new in C#7) use the old syntax, indexers have nothing to do with it(C#3):
public bool this[int index]
{
get { return _coolerFanIsOn[index]; }
set { _coolerFanIsOn[index] = value; }
}
You can write an indexer for your class
public bool this[int index]{
get { return coolerFanIsOn[index]; }
set { coolerFanIsOn[index] = value;}
}
Maybe this is what you would like to do:
class CoolerSystem
{
private CoolerFan[] _fans = new CoolerFan[5];
private bool[] _coolerfanIsOn;
public bool[] CoolerFanIsOn
{
get { return _coolerfanIsOn; }
set
{
_coolerfanIsOn = value;
}
}
public bool GetFanState(int number)
{
return CoolerFanIsOn[number];
}
public void SetFanState(int number, bool value)
{
CoolerFanIsOn[number] = value;
}
}
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.
hello I want to serialize a class in C# with a XMLserializer. The Compiler says that Room (myClass) is not primitive (i am using Unity3d) and therefor can not be serialized. The problem is that the most Tutorial are only for simple classes with a few simple fields. Can you help me changs Room to be serializable?
[Serializable]
public class Room
{
public Room()
{
m_id = "test";
m_section = Areas.PublicSec;
m_connections = null;
m_size = 10;
}
public Room(string _id, Areas _section, List<string> _connections, int _size)
{
// f.e. Bathroom
m_id = _id;
// private, public or hallway filled with the enum Areas
m_section = _section;
// list of rooms that have or will have a Connection
if (_connections != null)
{
m_connections = _connections;
}
else
{
m_connections = new List<string>();
}
//? Desired minium size of the room
m_size = _size;
}
private string m_id;
public string id
{
get { return m_id; }
set { m_id = value;}
}
private Areas m_section;
public Areas Section
{
get { return m_section; }
set { m_section = value; }
}
private List<string> m_connections;
[XmlArray("m_connections")]
public List<string> Connections
{
get { return m_connections; }
set { m_connections = value; }
}
private int m_size;
public int Size
{
get { return m_size; }
set { m_size = value; }
}
}
My XMLSerializer works with simple classes but not with this one.
Suppose class A as:
public class A
{
private string _str;
private int _int;
public A(string str)
{
this._str = str;
}
public A(int num)
{
this._int = num;
}
public int Num
{
get
{
return this._int;
}
}
public string Str
{
get
{
return this._str;
}
}
}
I want to hide Str property when i construct class A as
new A(2)
and want to hide Num property when i construct class A as
new A("car").
What should i do?
That isn't possible with a single class. An A is an A, and has the same properties - regardless of how it is constructed.
You could have 2 subclasses of abstract A, and a factory method...
public abstract class A
{
class A_Impl<T> : A
{
private T val;
public A_Impl(T val) { this.val = val; }
public T Value { get { return val; } }
}
public static A Create(int i) { return new A_Impl<int>(i); }
public static A Create(string str) { return new A_Impl<string>(str); }
}
But : the caller will not know about the value unless they cast it.
use generics
public class A<T>
{
private T _value;
public A(T value)
{
this._value= value;
}
public TValue
{
get
{
return this._value;
}
}
}
I want to transfer some data classes via Webservice:
public class MyClass
{
public int Int { get; set; }
public MyClass(int v)
{
Int = v;
}
private MyClass()
{
}
}
public enum MyEnum
{
One = 7,
Two = 13,
Three = 15
}
public class TestDataClass
{
private int _someInt;
public List<MyClass> Values { get; set; }
public int SomeInt
{
get
{
return _someInt + 10;
}
set { _someInt = value; }
}
public TestDataClass(int someInt)
{
SomeInt = someInt;
Values = new List<MyClass>();
for (int i = 0; i < 10; i++)
{
Values.Add(new MyClass(i));
}
}
private TestDataClass() {}
}
TestDataClass is the class beening passed, what should be attributed with serializable?
Thanks, Alex.
If you want to use the (old) ASMX style webservice: Yes.
When using WCF: No, use [DataContract] instead.
In both cases, you need attributes for the main class and for any embedded type that is not already Serializable or a 'known type'.