object linking consistency over network with binary serialisation - c#

I'm asking for more of an explanation more than anything about c# objects.
[Serializable]
class ExampleSub
{
public Example parent;
public ExampleSub(Example parent)
{
this.parent= parent;
}
}
[Serializable]
class Example
{
List<ExampleSub> subs;
public Example()
{
for (int i = 0; i < 10; i++)
subs.Add(new ExampleSub(this));
}
}
If I was to binary-serialise the Example class, with it containing the ExampleSubs in the list. Then sent it over a TCP connection, where on the other end it was deserialised back into an Example object. Would the ExampleSub's parent object point at the new Example object (as it should).
My question mostly is revolving around how the serialiser correctly maps the objects together, but also about how c# objects are identified at all really since the closest I can guess is that they act like smart-pointers.

Related

C# Cloning graph and updating circular references

Let me preface this by stating that I have seen similar posts to this, but none of the solutions have satisfied me and/or applied to C#.
I have a Graph class that consists of Node and Connection objects. The graph contains collections consisting of all of the child Node and Connection objects associated with it. In addition to this, each Node has a collection of Connection objects.
Please note: This is a simplified toy problem. You can view the actual (work-in-progress) production code here. In production, a Neuron is a Node and an Axon is a Connection.
public class Graph : IDeepCloneable<Graph>
{
// These are basically just Dictionary<int,object>s wrapped in an ICollection
public NodeCollection Nodes;
public ConnectionCollection Connections;
public Graph Clone()
{
return new Graph
{
Nodes = this.Nodes.Clone(),
Connections = this.Connections.Clone()
};
}
}
public class Node : IDeepCloneable<Node>
{
public int Id;
public NodeConnectionCollection Connections;
// NodeConnectionCollection is more or less the same as NodeCollection
// except that it stores Connection objects into '.Incoming' and '.Outgoing' properties
public Node Clone()
{
return new Node
{
Id = this.Id,
Connections = this.Connections.Clone()
};
}
}
public class Connection : IDeepCloneable<Connection>
{
public int Id;
public Node From;
public Node To;
public Connection Clone()
{
return new Connection
{
Id = this.Id,
From = this.From.Clone(),
To = this.To.Clone()
};
}
}
public class ConnectionCollection : ICollection<Connection>, IDeepCloneable<ConnectionCollection>
{
private Dictionary<int, Connection> idLookup;
private Dictionary<ProjectionKey, Connection> projectionLookup;
public int Count => idLookup.Count;
public bool IsReadOnly => false;
public Add( Connection conn )
{
idLookup.Add( conn.Id, conn );
projectionLookup.Add( new ProjectionKey( conn.From, conn.To ), conn );
}
...
internal struct ProjectionKey
{
readonly intFrom;
readonly int To;
readonly int HashCode;
public ProjectionKey( int from, int to )
{
From = from;
To = to;
HashCode = ( 23 * 397 + from ) * 397 + to;
}
public override int GetHashCode() { return HashCode; }
}
}
public class NodeCollection : ICollection<Node>, IDeepCloneable<NodeCollection>
{
private Dictionary<int, Node> nodes;
private Dictionary<int, InputNode> inputNodes;
private Dictionary<int, InnerNode> innerNodes;
private Dictionary<int, OutputNode> outputNodes;
...
public Node this[ int id ]
{
get => nodes[ id ];
}
}
Each of these objects support deep cloning, with the main idea being that consuming classes can call Clone() on child classes and work down the stack that way.
However, this is not viable in production. A call to Graph.Clone() will clone the NodeCollection and ConnectionCollection fields, which will clone each Node and Connection instance stored within them, which will each clone other referencing child elements.
A common solution seems to be storing the Ids of each child object and then rebuilding the references when all cloning is complete. However, as far as I am aware, this would require a reference to parent objects and tightly couple the data structure.
I am very puzzled at how to properly approach this. I require a reasonable amount of performance, as my application (a genetic algorithm) performs cloning constantly, but in this case I am more interested in finding a robust design pattern or implementation that will allow me to perform deep cloning of this graph structure while stashing a lot of the gruntwork behind the scenes.
Is there any design pattern that will allow me to clone this data structure as-is while updating circular references and maintaining its integrity?
My suggestion would be to change your approach to the problem from cloning to recreating. I've dealt with a resembling problem, where I was saving a graph user created manually from the user interface, and then upon an import of saved graph I was recreating it. It sounds almost the same if you think about it.
So the solution I came up with was serializing the graph from a central control (considering you are modifying graphs with an heuristic I assume you have central control over the graph). Even if you don't have a central control over the graph I believe it can be traversed in a way to get all the information.
In the simplest form a graph is a collection of neighborhood information.
Can be directed or undirected as well
1 -> 2
1 -> 3
3 -> 2
So if you can come up with a way to generate a list like this, after just tweaking this simple list, you can create your new graph.
Or another approach would be to list your nodes with their neighbors like below,
1, [2,3]
3, [2]
This would even be simpler to recreate the graph in my opinion.
Here is the file from the project I applied this approach if you are curious about - I don't think it would be a reference for the answer or question though.

C# Private member shared by all class instances

I am currently working with C# using the Unity3D engine and have come upon the following problem:
I created a class that has two private references to instances of another class which it has to access. Once I create multiple instances of the class and set the references I found out that all instances were using the same variable. I realized this as I was destroying an instance and just before that set the two variables holding the references to null. Immediately after doing that all other instances were throwing NullReferenceExceptions because they were still trying to access the references. The referenced objects are fine, other scripts can still access them.
Here is some pseudo code illustrating the structure:
public class Character
{
// Character data
}
public class StatusEffect
{
private Character target;
private Character originator;
public void Init(Character _Target, Character _Originator)
{
target = _Target;
originator = _Originator;
}
public void Destroy()
{
target = null;
originator = null;
}
}
In the program it would be called like this:
StatusEffect effect = new StatusEffect();
effect.Init(player1, player2);
// Time goes by
effect.Destroy();
After calling Destroy() every StatusEffect's two references will be null.
This is not only an issue when destroying StatusEffects, but also when creating new ones. As soon as I touch the references from within a new instance all StatusEffects will reference the two Characters specified by the new StatusEffect.
I do not understand why or how I can fix this issue. Can someone enlighten me on this matter?
Cheers,
Valtaroth
EDIT:
Here is the real code as requested:
I have a container class holding several StatusEffects. As soon as it starts, it initializes all of them.
public class CElementTag
{
// ..Other data..
public float f_Duration; // Set in the editor
private CGladiator gl_target;
private CGladiator gl_originator;
private float f_currentDuration;
public CStatusEffect[] ar_statusEffects;
// Starts the effect of the element tag
public void StartEffect(CGladiator _Originator, CGladiator _Target)
{
gl_originator = _Originator;
gl_target = _Target;
f_currentDuration = f_Duration;
for(int i = 0; i < ar_statusEffects.Length; i++)
ar_statusEffects[i].Initialize(gl_originator, gl_target);
}
// Ends the effect of the element tag
public void EndEffect()
{
for(int i = 0; i < ar_statusEffects.Length; i++)
{
if(ar_statusEffects[i] != null)
ar_statusEffects[i].Destroy();
}
}
// Called every update, returns true if the tag can be destroyed
public bool ActivateEffect()
{
f_currentDuration -= Time.deltaTime;
if(f_currentDuration <= 0.0f)
{
EndEffect();
return true;
}
for(int i = 0; i < ar_statusEffects.Length; i++)
{
if(ar_statusEffects[i] != null && ar_statusEffects[i].Update())
RemoveStatusEffect(i);
}
return false;
}
// Removes expired status effects
private void RemoveStatusEffect(int _Index)
{
// Call destroy method
ar_statusEffects[_Index].Destroy();
// Remove effect from array
for(int i = _Index; i < ar_statusEffects.Length - 1; i++)
ar_statusEffects[i] = ar_statusEffects[i+1];
ar_statusEffects[ar_statusEffects.Length - 1] = null;
}
}
The actual StatusEffect class is holding the two references as well as some other data it needs to work. It has virtual methods because there are some classes inheriting from it.
public class CStatusEffect
{
// ..Necessary data..
// References
protected CGladiator gl_target;
protected CGladiator gl_originator;
virtual public void Initialize(CGladiator _Target, CGladiator _Originator)
{
gl_target = _Target;
gl_originator = _Originator;
// ..Initialize other necessary stuff..
}
virtual public void Destroy()
{
gl_target = null;
gl_originator = null;
// ..Tidy up other data..
}
virtual public bool Update()
{
// ..Modifying data of gl_target and gl_originator..
// Returns true as soon as the effect is supposed to end.
}
}
That should be all the relevant code concerning this problem.
EDIT2
#KeithPayne I have a static array of ElementTags defined in the editor and saved to xml. At the beginning of the program the static array is loading the xml and stores all element tags. When creating a new element tag to use I utilize this constructor:
// Receives a static tag as parameter
public CElementTag(CElementTag _Tag)
{
i_ID = _Tag.i_ID;
str_Name = _Tag.str_Name;
enum_Type = _Tag.enum_Type;
f_Duration = _Tag.f_Duration;
ar_statusEffects = new CStatusEffect[_Tag.ar_statusEffects.Length];
Array.Copy(_Tag.ar_statusEffects, ar_statusEffects, _Tag.ar_statusEffects.Length);
}
Do I have to use a different method to copy the array to the new tag? I thought Array.Copy would make a deep copy of the source array and stored it in the destination array. If it is in fact making a shallow copy, I understand where the problem is coming from now.
From Array.Copy Method (Array, Array, Int32):
If sourceArray and destinationArray are both reference-type arrays or
are both arrays of type Object, a shallow copy is performed. A shallow
copy of an Array is a new Array containing references to the same
elements as the original Array. The elements themselves or anything
referenced by the elements are not copied. In contrast, a deep copy of
an Array copies the elements and everything directly or indirectly
referenced by the elements.
Consider this fluent version of the StatusEffect class and its usage below:
public class StatusEffect
{
public Character Target { get; private set; }
public Character Originator { get; private set; }
public StatusEffect Init(Character target, Character originator)
{
Target = target.Clone()
Originator = originator.Clone();
return this;
}
//...
}
public CElementTag(CElementTag _Tag)
{
i_ID = _Tag.i_ID;
str_Name = _Tag.str_Name;
enum_Type = _Tag.enum_Type;
f_Duration = _Tag.f_Duration;
ar_statusEffects = _Tag.ar_statusEffects.Select(eff =>
new StatusEffect().Init(eff.Target, eff.Originator)).ToArray();
// ar_statusEffects = new CStatusEffect[_Tag.ar_statusEffects.Length];
// Array.Copy(_Tag.ar_statusEffects, ar_statusEffects, _Tag.ar_statusEffects.Length);
}
Because you're passing in references to the objects via your Init() method, you're not actually "copying" the objects, just maintaining a reference to the same underlying objects in memory.
If you have multiple players with the same references to the same underlying objects, then changes made by player 1 will effect the objects being used by player 2.
Having said all that, you're not actually disposing the objects in your Destory method. Just setting the local instance references to Null which shouldn't affect any other instances of StatusEffects. Are you sure something else isn't disposing the objects, or that you haven't properly init'd your other instances.
If you do want to take a full copy of the passed in objects, take a look at the ICloneable interface. It looks like you want to pass in a copy of the objects into each Player.
public class Character : ICloneable
{
// Character data
//Implement Clone Method
}
public class StatusEffect
{
private Character target;
private Character originator;
public void Init(Character _Target, Character _Originator)
{
target = _Target.Clone()
originator = _Originator.Clone();
}
The fields aren't shared(static) among other instances. So calling target = null; in Destroy() won't affect other instances.
StatusEffect effect1 = new StatusEffect();
effect1.Init(player1, player2);
StatusEffect effect2 = new StatusEffect();
effect2.Init(player1, player2);
// Time goes by
effect2.Destroy();
// Some more time goes by
// accessing effect1.target won't give a `NullReferenceException` here unless player1 was null before passed to the init.
effect1.Destroy();
I think you did forget the Init(..) on the other instances. Every time you create an instance of StatusEffect, you need to call Init(...).
Update:
This line will clear the reference to the effect, but you never recreate it:
ar_statusEffects[ar_statusEffects.Length - 1] = null;
so the next time you call ar_statusEffects[x].Update() or Initialize() etc it will throw a NullReferenceException
If you want to clear out effects within you array, you could create an Enable bool in the effect, this way you only have to set/reset it.
for(int i = 0; i < ar_statusEffects.Length; i++)
if(ar_statusEffects[i].IsEnabled)
ar_statusEffects[i].Update();
Why don't you use a List instead? Arrays will be faster as long you don't have to shuffle in it. (like circulair buffers etc)
Thanks to Keith Payne I figured out where the problem was. I was creating a deep copy of CElementTag, but not of my ar_statusEffects array. I wrongly assumed Array.Copy was creating a deep copy of an array when it actually was not.
I implemented the IClonable interface for my CStatusEffect and use the Clone() method to create a true deep copy for each member of the static array and add it to the new tags ar_statusEffects array. This way I have seperate instances of the effects instead of references to the same static effect.
Thanks to everyone, especially Keith Payne, for their help and support!

Objects containing list of same object type

Is there anything wrong with defining something like this:
class ObjectA
{
property a;
property b;
List <ObjectA> c;
...
}
No, and because the answer needs at least 30 characters, I'll add that this is a common pattern.
Since you included the oop tag, though, I'll add that this pattern gives a lot of control to the outside world. If c is a list of children, for example, you're giving everyone who has access to an instance of ObjectA the ability to add, delete, or replace its children.
A tighter approach would be to use some sort of read-only type (perhaps implementing IList<ObjectA>) to expose the children.
EDIT
Note that the following still allows others to modify your list:
class ObjectA
{
property a;
property b;
List <ObjectA> c;
...
public List<ObjectA> Children { get { return c; } }
}
The absence of a setter only prevents outsiders from replacing the list object.
Nope. That's perfectly acceptable. Tree structures do this.
It is perfectly valid. For example, you would have to do something like this to build a tree data structure (parent node contains a list of child nodes).
i have to ask if your question is about putting a List< > in there, or if it is about putting a List< ObjectA > inside of ObjectA. and the answer to both questions is "Yes"!
the thing to keep in mind is that by default, the access is private. if you want other classes to use this list, then you need to add a few things to your class...
class ObjectA
{
property a;
property b;
List <ObjectA> c;
// allow access, but not assignment
// you can still modify the list from outside, you just cant
// assign a new list from outside the class
public List<ObjectA> somePropertyName{ get { return this.c;}}
// same as above, only allow derived child classes to set the list
public List<ObjectA> somePropertyName{ get { return this.c;}
protected set { this.c = value;} }
// allow all access
public List<ObjectA> somePropertyName{ get { return this.c;}
set { this.c = value;} }
}
No. This is valid. Many structures uses this graph like pattern.
If you eg have a base collection class
namespace MiniGraphLibrary
{
public class GraphCollection
{
public Node Root { set; get; }
public Node FindChild(Node root)
{
throw new NotImplementedException();
}
public Node InsertNode(Node root, Node nodeToBeInserted)
{
throw new NotImplementedException();
}
}
}
Then you can have the node act like this:
namespace MiniGraphLibrary
{
public class Node
{
private string _info;
private List<Node> _children = new List<Node>();
public Node(Node parent, string info)
{
this._info = info;
this.Parent = parent;
}
public Node Parent { get; set; }
public void AddChild(Node node)
{
if (!this.DoesNodeContainChild(node))
{
node.Parent = this;
_children.Add(node);
}
}
public bool DoesNodeContainChild(Node child)
{
return _children.Contains(child);
}
}
}
Note that this is something I wrote in 2 minutes, and it is problery not good in production, but the 2 main things is that you have a parent node and many children. When you add a child node to a given node, then you make sure that it has its parent node set. Here I first check if the child is allready in the children list before connection the two.
You could make some changes to the code, and make sure that if a child is removed an parent lists that it is allready connected to. I have not done this there.
I have made this to illustrate how it could be used. And it is used many places. Fx clustered indexes in MSSQL uses some sort of this tree like representation. But I am NOT an expert on this subject, so correct me if I am wrong.
I have not implemented the two classes in the GraphCollection class. The downside of my little example is that you if you are going to implement the Find method, then you have to go through the whole graph. You could make a binary tree that only has two children:
namespace MiniTreeLibrary
{
public class SimpleNode
{
private string _info;
private SimpleNode _left;
private SimpleNode _right;
private SimpleNode _parent;
public SimpleNode(Node parent, string info)
{
this._info = info;
this.Parent = parent;
}
public Node Parent { get; private set; }
}
}
I have omitted the insertion of the right and left. Now with this binary tree you could do some pretty darn fast searching, if you wanted!! But that is another discossion.
There is many rules when it comes trees and graphs, and my graph is even a real graph. But I have put these examples here so you can see that it is used alot!! If you want to go more into linear and other data structures, then see this serie of articles. Part 3, 4 and 5 they talks alot more about trees and graphs.

Generic Linked List

Before posting my question, I would like to tell you that I have no prior experience in .Net technologies and have recently started to learn C# (and WPF). My company is looking to move onto .Net technologies and I am the only one in my team learning it, so have noone apart from you guys to discuss or ask something. So if my questions are too stupid or basic at best, please bear with me.
I was trying to create a generic linked list class to allow creation of linked lists of different types. I wrote the following code and would like to have your advise on whether I have written this code properly or not. Any suggestions to improve the code in any way is most welcome.
Main program
class Program
{
static void Main(string[] args)
{
GenLinkedList<string> list = new GenLinkedList<string>("abc");
list.AddtoList("def");
int i = 0;
string[] arr = new string[10];
list.LinkedList.CopyTo(arr,0);
for (i = 0; i < list.LinkedList.Count; i++)
{
Console.WriteLine(arr[i]);
}
GenLinkedList<int> listInt = new GenLinkedList<int>(1);
listInt.AddtoList(2);
i = 0;
int[] arrInt = new int[10];
listInt.LinkedList.CopyTo(arrInt, 0);
for (i = 0; i < listInt.LinkedList.Count; i++)
{
Console.WriteLine(arrInt[i]);
}
}
}
Class GenLinkedList
public class GenLinkedList<T>
{
private LinkedList<T> _linkedlist;
public GenLinkedList(T a)
{
_linkedlist = new LinkedList<T>();
_linkedlist.AddLast(a);
}
public LinkedList<T> LinkedList
{
get
{
return _linkedlist;
}
}
public void AddtoList(T a)
{
LinkedList.AddLast(a);
}
}
Why not use System.Collections.Generic.LinkedList<T>? You're using it internally in your GenLinkedList<T> already and it's already Generic for you.
It's the Framework Provided Generic Doubly Linked List implementation. Read up on it at:
MSDN - LinkedList(T) Class
If you're creating a Generic Linked List as an exercise, you shouldn't base your implementation of of an existing Generic Linked List. You're really not going to be learning anything by wrapping something that already does exactly what you need to do.
1
A generic linked list implementation already exists in the .NET framework: LinkedList<T>. But you already know that; your code wraps it.
2
OK, so you know that. Why would you wrap it, then? The only functionality you appear to have implemented is AddtoList, which doesn't do anything the LinkedList<T> doesn't already do itself (after all, this is only a thin wrapper around LinkedList<T>.AddLast). What this means is that your GenLinkedList<T> class really doesn't offer the functionality of a linked list; it's basically an add-only collection (which could just as easily have been implemented with a List<T>, or a Stack<T>, or a Queue<T> -- anything, really).
3
Assuming you do have a good reason to wrap a LinkedList<T> (e.g., you're planning to add more functionality down the line that would actually leverage the behavior of a LinkedList<T> and/or -- here's a key ingredient -- you want to restrict the way calling code is able to interact with the list (e.g., no removals)), you really shouldn't expose your LinkedList<T> member at all. The purpose of a wrapper is just that: to wrap. You take an existing class and basically give it a new kind of interface. By exposing the underlying object directly, you cripple your wrapper. Any additional restrictions/validation/logic you have in your wrapper can be bypassed.
So, for example, if you want to be able to copy your list to an array, instead of doing this:
list.LinkedList.CopyTo(arr,0);
You would implement a CopyTo method within your GenLinkedList<T> class (which could simply call _linkedlist.CopyTo) and use that.
But I really think the first question you should be asking yourself is what you want to accomplish by wrapping LinkedList<T> in the first place.
The obvious question is why you don't just use LinkedList<T> directly, although it looks like you're trying to emulate a singly-linked list.
In this case, you should avoid exposing the underlying LinkedList<T> instance, since any client could manipulate it directly. I would also implement IEnumerable<T> which will make your list usable by linq.
I got this from http://msdn.microsoft.com/en-us/library/0x6a29h6.aspx
Works fine with me.
namespace GenLinkedList
{
class Program
{
static void Main(string[] args)
{
GenericList<object> list = new GenericList<object>();
// Add items to list.
list.AddHead("some string here");
list.AddHead(DateTime.Today.ToLongDateString());
list.AddHead(13);
list.AddHead(13.005);
for (int x = 0; x < 10; x++)
{
list.AddHead(x);
}
// Enumerate list.
foreach (object i in list)
{
Console.WriteLine(i + " " + i.GetType());
}
Console.WriteLine("\nDone");
}
}
}
namespace GenLinkedList
{
// type parameter T in angle brackets
class GenericList<T>
{
// The nested class is also generic on T.
public class Node
{
private Node next;
// T as private member data type.
private T data;
// T used in non-generic constructor.
public Node(T t)
{
next = null;
data = t;
}
public Node Next
{
get { return next; }
set { next = value; }
}
public T Data
{
get { return data; }
set { data = value; }
}
}
private Node head;
// constructor
public GenericList()
{
head = null;
}
// T as method parameter type
public void AddHead(T t)
{
Node n = new Node(t);
n.Next = head;
head = n;
}
public IEnumerator<T> GetEnumerator()
{
Node current = head;
while (current != null)
{
yield return current.Data;
current = current.Next;
}
}
}
}

How do you serialize/deserialize a list of objects with a common root class?

Related: How can I use polymorphism in XML Serialization?
I have a class I wrote for serializing the user's preferences to disk between application sessions. To read/write I'm using XmlSerializer.Deserialize() and XmlSerializer.Serialize(). One property that gets serialized is a list of sub-settings for different application components. To accomplish this, I have something like the following (the property is only used during serialization):
private readonly Dictionary<SettingType, SubSettings> subSettings;
[XmlArray("SubSettings")]
[XmlArrayItem("SubSetting", Type=typeof(DictionaryEntry))]
public DictionaryEntry[] _SubSettings
{
get
{
int i = 0;
//Make an array of DictionaryEntries to return
DictionaryEntry[] result = new DictionaryEntry[subSettings.Count];
foreach( KeyValuePair<SettingType, SubSettings> setting in subSettings ) {
DictionaryEntry entry = new DictionaryEntry( setting.Key, setting.Value );
result[i] = entry;
i++;
}
return result;
}
set
{
subSettings.Clear();
for( int i = 0; i < value.Length; i++ )
subSettings.Add( (SettingType)value[i].Key, (SubSettings)value[i].Value );
}
}
That's been serving me perfectly well, with all the dictionary's values being SubSettings dynamically. The problem is that now I'd like to have some of the SubSettings objects be a different dynamic type (CoolSubSettings : SubSettings). The obvious problem is that if I do this, I won't be able to communicate as the XML is read what dynamic type each SubSettings node is supposed to be, and its additional properties will not be read or written.
This is because serializer does not know all the types, you must tell him which types it must use. For example, you cant try the following approach:
struct DictEntry<T>
{
public SettingType Key;
public T Value;
}
// ...
[XmlArray("SubSettings")]
[XmlArrayItem("SubSetting", Type=typeof(DictEntry<SubSettings>))]
[XmlArrayItem("CoolSubSetting", Type=typeof(DictEntry<CoolSubSettings>))]
public object[] _SubSettings
{
// ...
Update: Yet another solution for your problem:
struct DictEntry
{
public SettingType Key;
[XmlElement("SubSettingValue", Type=typeof(SubSettings))]
[XmlElement("CoolSubSettingValue", Type=typeof(CoolSubSettings))]
public object Value;
}
[XmlArray("SubSettings")]
public DictEntry[] _SubSettings
{
// ...
I think you understand main implementation idea? BTW, I am not sure about inheritance in this case, and I cannot test it right now. But in case of troubles you can create basic ancestor for both SubSettings and CoolSubSettings.

Categories