I'm new in C# and I am completing the book "Microsoft Visual C# 2013 Step by Step" written by John Sharp.
An exercise, regarding "Generics", I found this code:
public class Tree<TItem> where TItem : IComparable<TItem>
{
public TItem NodeData { get; set; }
public Tree<TItem> LeftTree { get; set; }
public Tree<TItem> RightTree { get; set; }
public Tree(TItem nodeValue)
{
this.NodeData = nodeValue;
this.LeftTree = null;
this.RightTree = null;
}
public void Insert(TItem newItem)
{
TItem currentNodeValue = this.NodeData;
if (currentNodeValue.CompareTo(newItem) > 0)
{
// Insert the new item into the left subtree
// code here....
}
else
{
// Insert the new item into the right subtree
// code here....
}
}
}
I can't understand why he defined the properties in different mode.
One in this way:
public TItem NodeData { get; set; }
And the others in this:
public Tree<TItem> LeftTree { get; set; }
public Tree<TItem> RightTree { get; set; }
Someone can explain me why? Thank you
These properties are being used for different things. As their name suggest:
NodeData is used to facilitate the information stored in the tree.
LeftTree/RightTree are there to facilitate the topology of the tree - each current object (node) is basically a root of a tree rooted at itself. So as it is a binary tree it has two direct descendants - the left and the right nodes.
Where the part where the generics come to play is about the what is the kind of data stored in the tree. So the NodeData is trivially of "type" TItem. The left and right nodes are of type Tree<TItem> so to ensure that at any depth of the tree it is a TItem type of data that is stored.
To make it simpler lets suppose that you wanted to create a binary tree of integers. Then you'd model it by:
public class Tree
{
public int Data { get; set; }
public Tree Left {get; set; }
public Tree Right {get; set; }
}
I think this way you can really see what is the fundamental difference between the Data and Left, Right properties.
He defines a tree. The NodeData property is the current node value. Then if the value is smaller than the the current node, the new value is put on the left, otherwise on the right. If the type of LeftValue and RightValue are Tree, it's to have a parent-child structure. This class allows to create a data structure like binary tree.
Related
I tried creating a Binary tree assuming it will have max of 2 child nodes. But for a graph it will have one or more graph nodes connected to it. How can I create a simple class for a graph node like the below which I created for a tree. The reason for suggestion is because I am trying for a simple code to find all nodes info tied to a particular node.
class TreeNode
{
public int value { get; set; }
public TreeNode leftNode { get; set; }
public TreeNode rightNode { get; set; }
}
In case of graph, any node can have arbitrary many edges (neighbor nodes), so you have to use a collection, say List<T>:
// TValue - let's generalize
// (e.g. you may want ot have double or string value associated with the node)
class GraphNode<TValue> {
private List<GraphNode<TValue>> m_Connected = new List<GraphNode<TValue>>();
public TValue value { get; set; }
// get (and no set) - we don't want to assign the collection as whole
// if we want to add/remove a neighbor we'll call Neighbors.Add, Neighbors.Remove
public List<GraphNode<TValue>> Neighbors {
get {
return m_Connected;
}
}
}
I have a general question about the structure of my object model. Perhaps I am approaching this with tunnel vision from the wrong direction. I have two classes, Item and SerializedItem. I have defined them as such:
public class Item
{
public string ItemNumber { get; set; }
public string Description { get; set; }
public double Cost { get; set; }
}
public class SerializedItem : Item
{
public string SerialNumber { get; set; }
public MyObject Location { get; set; }
}
An Item is a generic definition of an item, and contains information common to that product. SerializedItem is a representation of a specific, physical item. My difficulty lies in the fact that only one Item with a particular ItemNumber should exist in memory at anytime, and I am not sure the best pattern to use to enforce that constraint while allowing a SerializedItem to act as its base type.
Maybe this is a more appropriate approach? I don't have a lot of experience using the 'New' keyword, and I've shied away from using it in the past in favor of an inheritance structure that didn't require its use.
public class Item
{
public string ItemNumber { get; set; }
public string Description { get; set; }
public double Cost { get; set; }
}
public class SerializedItem : Item
{
private Items _item;
public SerializedItemz(Item item)
{
_item = item;
}
public new string ItemNumber
{
get { return _item.ItemNumber; }
set { _item.ItemNumber = value; }
}
public new string Description
{
get { return _item.Description; }
set { _item.Description = value; }
}
public new double Cost
{
get { return _item.Cost; }
set { _item.Cost = value; }
}
public string SerialNumber { get; set; }
}
I would appreciate any guidance on how to approach this. I'm not tied to any particular solution.
To provide some clarity:
The Item class is a representation of a particular product, 'Widget A.' It has information about the Widget A's cost, weight, dimensions, etc. No matter how many Widget As are produced, they all share this information.
The SerializedItem class is a representation of an actual item in that product line, 'Widget A 001.' It contains information about the physical location of that item and it's production and sales history.
If the Item object is updated, all SerializedItems should reflect that change.
I am not sure the best pattern to use to enforce that constraint while allowing a SerializedItem to act as its base type
At first glance a flyweight factory pattern would seem appropriate. Create a class whose responsibility is to create Items, keep track of which ones have already been created, and ensure that only one item with a given key is created.
You can also build logic into the factory to create different subtypes like SerializedItem - you'd just need to provide the appropriate SPI to determine what type is necessary and collect the necessary inputs.
A basic implementation would look something like:
public static class ItemFactory
{
public static Dictionary<string, Item> _Items = new Dictionary<string, Item>;
public static Item GetItem(string itemNumber)
{
if(!_Items.ContainsKey(itemNumber))
{
_Items[itemNumber] = new Item(itemNumber);
// Initialize item if necessary
}
return _Items[itemNumber];
}
}
The SerializedItem class is a representation of an actual item in that product line
Than an appropriate design is to make Item an ItemType and use composition instead of inheritance. So your second approach (with the change that SerializedItem does NOT inherit from Item) looks valid.
If Item is truly a non-instantiated base class then mark it as abstract and work through your concrete SerializedItem class ( and any other derived classes you may have ). If you only want a single Item in memory with a given item number then you might consider a Dictionary type collection indexed on the item number.
I need to build a typed list of parent-child objects that are read from two different Excel sources: One describes parent object, another describes child objects. The hierarchy is only 2 layers ever.
Reading into excel is not the issue, as it is read into 2 untyped datatables, but joining the information is.
The structure is very plain:
Parent has an ID and some text fields
Children have a parentID (so its 1-m) and some text fields
The objects that these are to be populated into looks like this:
public class ParkingSites
{
public List<ParkingLot> Lots { get; set; }
public ParkingSites(List<ParkingLot> arg)
{
Lots = arg;
}
}
public class ParkingLot
{
public List<Bay> Bays{ get; set; }
public int Id { get; set; }
public List<string> ParkingLotDetails { get; set; }
public ParkingLot()
{
}
}
public class Bay
{
public List<string> BayDetails { get; set; }
public int ParentId { get; set; }
public Bay()
{
}
}
The excel sources have a fixed column order with the parent sheet's first column being the parentId, and the first column on the child sheet also being the parentId.
EDIT: After playing around a bit, I just made both parent and child classes typed, as the initial reason for leaving them mostly untyped lead to more problems than it prevented. This is part of a larger project where the untypedness is a better solution for our problem on the other classes with data that is not hierarchial.
You can simply group the list of children by the parent id, and then iterate over the parents and add each child that belongs to it.
For example, you could use ToLookup:
// assuming you have all Bay instances in a collection called bays
var baymap = bays.ToLookup(b => b.ParentId);
// and all ParkingLot instances in a collection called lots
foreach(var lot in lots)
lot.Bays.AddRange(baymap[lot.Id]);
or, using the first element in the details lists:
var baymap = bays.ToLookup(b => b.BayDetails[0]);
foreach(var lot in lots)
lot.Bays.AddRange(baymap[lot.ParkingLotDetails[0]]);
or, using Where without a lookup (probably slower, depends on your data):
foreach(var lot in lots)
lot.Bays.AddRange(bays.Where(b => b.ParentId == lot.Id));
I have a mongo model like this:
class ObjectA {
[BsonId(IdGenerator = typeof(BsonObjectIdGenerator))]
public BsonObjectId Id;
[BsonElement("number")]
public int Number { get; set; }
[BsonElement("b")]
public List<ObjectB> objectB { get; set; }
}
class ObjectB {
[BsonElement("someProperty")]
public string SomeProperty { get; set; }
}
My problem is when I aggregate the collection with {$unwind:objectB}. The result documencts have a unique object on the property objectB (not a list).
So the cast failes with the exception:
An error occurred while deserializing the ObjectB property of class
ObjectA: Expected element name to be '_t', not
'number'.
Do I have to create a new model for this or is there a easier way to solve it?
You could also choose to work with BsonDocument directly (but that is not strongly typed and more cumbersome to work with), e.g. (I'm using the simple Posts/Tags example here)
var aggregationResults = db.GetCollection("Posts").Aggregate().ResultDocuments;
foreach (var document in aggregationResults)
{
var tag = document.GetValue("Tags").AsString;
}
Unlike the normal query and projection operators, the aggregation framework may change the structure of your document. As you already pointed out, $unwind transforms a document that contains an array into a number of documents that each have a single value of the same name.
Another approach this is to indeed create a new type for this, so
class Post {
public List<string> Tags { get; set; }
...
would become
class PostAggregationResult {
public string Tags { get; set; }
...
That is very easy to work with, but if you have very various aggregation queries, you need a large number of classes which can be annoying.
Lets say I have a Node class as follows:
class Node<T>
{
T data;
List<Node<T>> children;
internal Node(T data)
{
this.data = data;
}
List<Node<T>> Children
{
get
{
if (children == null)
children = new List<Node<T>>(1);
return children;
}
}
internal IEnumerable<Node<T>> GetChildren()
{
return children;
}
internal bool HasChildren
{
get
{
return children != null;
}
}
internal T Data
{
get
{
return data;
}
}
internal void AddChild(Node<T> child)
{
this.Children.Add(child);
}
internal void AddChild(T child)
{
this.Children.Add(new Node<T>(child));
}
}
The problem is that each and every node of the tree is confined to a single type. However, there are situations where the root node is of one type, which has children of another type which has children of a third type (example documents-->paragraphs-->lines-->words).
How do you define a generic tree for such cases?
If you want a strict hierarchy of types you could declare them like this:
class Node<T, TChild> {...}
Node<Document, Node<Paragraph, Node<Line, Word>>>
I did not claim it would be pretty. :)
How do you define a generic tree for such cases?
I wouldn't try to in the first place. If what I wanted to model was:
I have a list of documents
A document has a list of paragraphs
A paragraph has a list of words
then why do you need generic nodes at all? Make a class Paragraph that has a List<Word>, make a class Document that has a List<Paragraph>, and then make a List<Document> and you're done. Why do you need to artificially impose a generic tree structure? What benefit does that buy you?
Have all of your sub-objects implement a specific eg IDocumentPart then declare Node
I have been reluctant to offer the code example attached, feeling that I don't have a strong sense, yet, of the "norms" of StackOverFlow in terms of posting code that may be "speculative," and, feeling that this particular frolic is some form of "mutant species" escaped from the laboratory on "The Island of Dr. Moreau" :) And, I do think the answer by Eric Lippert above is right-on.
So please take what follows with "a grain of salt" as just an experiment in "probing" .NET inheritance (uses FrameWork 3.5 facilities). My goal in writing this (a few months ago) was to experiment with an Abstract Class foundation for Node structure that implemented an internal List<> of "itself," then implement strongly-typed classes that inherited from the Abstract class ... and, on that foundation, build a generalized Tree data structure.
In fact I was surprised when I tested this, that it worked ! :)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
// experimental code : tested to a limited extent
// use only for educational purposes
namespace complexTree
{
// foundation abstract class template
public abstract class idioNode
{
// a collection of "itself" !
public List<idioNode> Nodes { private set; get; }
public idioNode Parent { get; set; }
public idioNode()
{
Nodes = new List<idioNode>();
}
public void Add(idioNode theNode)
{
Nodes.Add(theNode);
theNode.Parent = this;
}
}
// strongly typed Node of type String
public class idioString : idioNode
{
public string Value { get; set; }
public idioString(string strValue)
{
Value = strValue;
}
}
// strongly typed Node of type Int
public class idioInt : idioNode
{
public int Value { get; set; }
public idioInt(int intValue)
{
Value = intValue;
}
}
// strongly type Node of a complex type
// note : this is just a "made-up" test case
// designed to "stress" this experiment
// it certainly doesn't model any "real world"
// use case
public class idioComplex : idioNode
{
public Dictionary<idioString, idioInt> Value { get; set; }
public idioComplex(idioInt theInt, idioString theString)
{
Value = new Dictionary<idioString, idioInt>();
Value.Add(theString, theInt);
}
public void Add(idioInt theInt, idioString theString)
{
Value.Add(theString, theInt);
theInt.Parent = this;
theString.Parent = this;
}
}
// special case the Tree's root nodes
// no particular reason for doing this
public class idioTreeRootNodes : List<idioNode>
{
public new void Add(idioNode theNode)
{
base.Add(theNode);
theNode.Parent = null;
}
}
// the Tree object
public class idioTree
{
public idioTreeRootNodes Nodes { get; set; }
public idioTree()
{
Nodes = new idioTreeRootNodes();
}
}
}
So, to the test : (call this code from some EventHandler on a WinForm) :
// make a new idioTree
idioTree testIdioTree = new idioTree();
// make a new idioNode of type String
idioString testIdioString = new idioString("a string");
// add the Node to the Tree
testIdioTree.Nodes.Add(testIdioString);
// make a new idioNode of type Int
idioInt testIdioInt = new idioInt(99);
// add to Tree
testIdioTree.Nodes.Add(testIdioInt);
// make another idioNode of type String
idioString testIdioString2 = new idioString("another string");
// add the new Node to the child Node collection of the Int type Node
testIdioInt.Nodes.Add(testIdioString2);
// validate inheritance can be verified at run-time
if (testIdioInt.Nodes[0] is idioString) MessageBox.Show("it's a string, idiot");
if (!(testIdioInt.Nodes[0] is idioInt)) MessageBox.Show("it's not an int, idiot");
// make a new "complex" idioNode
// creating a Key<>Value pair of the required types of idioNodes
idioComplex complexIdio = new idioComplex(new idioInt(88), new idioString("weirder"));
// add a child Node to the complex idioNode
complexIdio.Add(new idioInt(77), new idioString("too weird"));
// make another idioNode of type Int
idioInt idioInt2 = new idioInt(33);
// add the complex idioNode to the child Node collection of the new Int type idioNode
idioInt2.Nodes.Add(complexIdio);
// add the new Int type Node to the Tree
testIdioTree.Nodes.Add(idioInt2);
// validate you can verify the type of idioComplex at run-time
MessageBox.Show(" tree/2/0 is complex = " + (testIdioTree.Nodes[2].Nodes[0] is idioComplex).ToString());
If the "smell" of this code is as bad as the fruit that here in Thailand we call the "durian" : well, so be it :) An obvious possible "weirdness" in this experiment is that you could have references to the same Node in more than one place in the tree at the same time.