How I can make a method to calculate the sum of listOfNodes objects? I was doing with foreach statement like
foreach(int s in listOfNodes)
sum += s;
to get all the nodes but it didn't worked.
It says:
Error 1 foreach statement cannot operate on variables of type 'ConsoleApplication1.Program.List' because 'ConsoleApplication1.Program.List' does not contain a public definition for 'GetEnumerator' C:\Users\TBM\Desktop\I\ConsoleApplication1\ConsoleApplication1\Program.cs 24 13 ConsoleApplication1
My code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
List listOfNodes = new List();
Random r = new Random();
int sum = 0;
for (int i = 0; i < 10; i++)
{
listOfNodes.addObjects(r.Next(1, 100));
}
listOfNodes.DisplayList();
Console.ReadLine();
}
class ListNode
{
public object inData { get; private set; }
public ListNode Next { get; set; }
public ListNode(object dataValues)
: this(dataValues, null) { }
public ListNode(object dataValues,
ListNode nextNode)
{
inData = dataValues; Next = nextNode;
}
} // end class ListNode
public class List
{
private ListNode firstNode, lastNode;
private string name;
public List(string nameOfList)
{
name = nameOfList;
firstNode = lastNode = null;
}
public List()//carieli list konstruktori saxelis "listOfNodes"
: this("listOfNodes") { }
public void addObjects(object inItem)
{
if (isEmpty())
{ firstNode = lastNode = new ListNode(inItem); }
else { firstNode = new ListNode(inItem, firstNode); }
}
private bool isEmpty()
{
return firstNode == null;
}
public void DisplayList()
{
if (isEmpty())
{ Console.Write("Empty " + name); }
else
{
Console.Write("The " + name + " is:\n");
ListNode current = firstNode;
while (current != null)
{
Console.Write(current.inData + " ");
current = current.Next;
}
Console.WriteLine("\n");
}
}
}//end of class List
}
}
As the error message says, you need to implement GetEnumerator in order to foreach over something. So, implement GetEnumerator:
public IEnumerator GetEnumerator()
{
ListNode node = firstNode;
while (node != null)
{
yield return node;
node = node.Next;
}
}
You can now have your List class implement the IEnumerable interface too, if you want.
The alternative would be to not use a foreach loop, and instead use a while loop, as I did here, or you did in your DisplayList method.
Related
I've been attempting to write a section of code for this project so that it can print out whichever BasePlayer object's hand along with the total as such (: (card) (card) (total) - (playerName)) and I've been trying to override ToString() to be able to accomplish this. Issue is I need to pass the referenced object's specific hand but can't figure out how to pass by reference while using an override. I'm not sure if it's syntax or how I'm doing it, I would just like to fix it.
The issue is the bottom most function:
using System;
using System.Collections.Generic;
using System.Text;
using Blackjack_C;
namespace Blackjack_C
{
public class BasePlayer : Hand
{
public string name;
private (ref BasePlayer ap);
public BasePlayer(ref string name)
{
this.name = name;
}
Hand hand = new Hand();
public bool IsBusted()
{
return hand.getTotal() > 21;
}
public void Bust()
{
Console.Write(name + " busts.");
}
public override string ToString(ref BasePlayer ap)
{
string output = ":\t";
if (!(ap.m_Cards.Count == 0))
{
foreach (var c in ap.m_Cards)
{
output += (c + "\t");
}
if (ap.getTotal() != 0)
{
output += ("(" + ap.getTotal() + ")");
}
return output;
}
else
{
return("<empty>");
}
}
}
}
Here is the definition of the Hand class:
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using Blackjack_C;
namespace Blackjack_C
{
public class Hand
{
protected List<Card> m_Cards;
~Hand()
{
clearHand();
}
public void add(Card pCard)
{
m_Cards.Insert(m_Cards.Count, pCard);
}
public void clearHand()
{
m_Cards.Clear();
}
public int getTotal()
{
// If the hand is empty it cannot get total
if (m_Cards.Count == 0)
{
return 0;
}
// Gets total value of deck (doesn't run if Dealer's hand)
int total = 0;
foreach (var c in m_Cards)
{
total += c.getValue();
}
// Bool to check if the hand has an Ace in it (doesn't run if Dealer's hand)
bool containsAce = false;
foreach (var c in m_Cards)
{
if (c.getValue() == (int) Card.card_face.Ace)
{
containsAce = true;
}
}
// Checks if hand is dealer's hand and get's value whilst keeping it secret from the player
if (m_Cards.First().getValue() == 0)
{
//int total = 0;
foreach (var c in m_Cards)
{
total += c.getDealerValue();
}
//bool containsAce = false;
foreach (var c in m_Cards)
{
if (c.getDealerValue() == (int) Card.card_face.Ace)
{
containsAce = true;
}
}
}
// Checks if total is less than 11 to see if changing Ace to = 11 instead of = 1 is necessary
if (containsAce && total <= 11)
{
total += 10;
}
return total;
}
public Card getCard(int index)
{
if (index >= m_Cards.Count || index < 0)
return m_Cards[0];
else
{
return m_Cards[index];
}
}
}
}
Sorry for lack of a good post, this is my first time posting a question here.
i created the hand object with assumptions. Hand can have 2 or more card.
so you can try like this :
public class BasePlayer
{
public Hand Hand { get; set; }
public string Name { get; set; }
public BasePlayer(ref string name)
{
Name = name;
}
public bool IsBusted()
{
return Hand.GetTotal() > 21;
}
public void Bust()
{
Console.Write(Name + " busts.");
}
public override string ToString()
{
// you can access referenced string and specific hand on here
return string.Join(' ',Hand.Cards.Select(card=>$"{(card)}")) + $" {(Hand.GetTotal()) } "+ Name;
}
}
public class Hand
{
public List<int> Cards { get; set; }
public int GetTotal()
{
return Cards.Sum();
}
}
I have a small winforms program for a task which is to create a Recipe book. The application has two windows, but my bug pertains to only one.
I have two main classes: Recipe.cs and RecipeManager.cs, the idea is that the RecipeManager holds an array of Recipes. (For this task we weren't allowed to use Linq or ArrayLists)
Now, when I fill in the form and click "Add Recipe", the first one works successfully and the listBox populates correctly, however the second time I "Add Recipe" the recipeList array seems to get rewritten with the new Recipe entirely, and I have no idea why this is happening. The recipeList seems to change before my Add method even adds it to the array!
See gif of problem in question:
https://i.imgur.com/sIMICcG.gifv
Recipe.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace programmingTask4
{
public class Recipe
{
private string[] ingredientArray;
private string name;
private FoodCategory category;
private string description;
private const int maxNumOfIngredients = 20;
public string Name
{
get { return name; }
set { name = value; }
}
public FoodCategory Category
{
get { return category; }
set { category = value; }
}
public string Description
{
get { return description; }
set { description = value; }
}
public string[] Ingredient
{
get { return ingredientArray; }
set { ingredientArray = value; }
}
public int MaxNumOfIngredients
{
get { return ingredientArray.Length; }
}
public Recipe(int maxNumOfIngredients)
{
Console.WriteLine("Recipe constructor was called!");
ingredientArray = new string[maxNumOfIngredients];
DefaultValues();
}
public void DefaultValues()
{
for (int i = 0; i < ingredientArray.Length; i++)
{
ingredientArray[i] = string.Empty;
name = string.Empty;
category = FoodCategory.Vegetarian;
description = string.Empty;
}
}
public int FindVacantPosition()
{
int results;
for (int i = 0; i < ingredientArray.Length; i++)
{
if(ingredientArray[i] == string.Empty)
{
results = i;
return results;
}
}
return -1;
}
public bool AddIngredient(string value)
{
bool ok;
int next = FindVacantPosition();
if(next >= 0)
{
ok = true;
ingredientArray[next] = value;
}
else {
ok = false ;
}
return ok;
}
public bool CheckIndex(int index)
{
bool check = false;
if(index <= ingredientArray.Length && index >= 0)
{
check = true;
}
return check;
}
public int GetCurrentNumOfIngredients()
{
int count = 0;
for (int i = 0; i < ingredientArray.Length; i++)
{
if (!string.IsNullOrEmpty(ingredientArray[i]))
{
count++;
}
}
return count;
}
public override string ToString()
{
int chars = Math.Min(description.Length, 15);
string descriptionText = description.Substring(0, chars);
if (string.IsNullOrEmpty(descriptionText))
descriptionText = "NO DESCRIPTION";
string textOut = string.Format("{0, -20} {1,4} {2,-12} {3,-15}", name, GetCurrentNumOfIngredients(), category.ToString(), descriptionText);
return textOut;
}
public bool ChangeIngredientAt(int index, string value)
{
bool bok = true;
if (CheckIndex(index))
ingredientArray[index] = value;
else
bok = false;
return bok;
}
public bool DeleteIngredientAt(int index)
{
bool bok = true;
if (CheckIndex(index))
ingredientArray[index] = "NO DESCRIPTION";
else
bok = false;
return bok;
}
}
}
RecipeManager.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace programmingTask1
{
class RecipeManager
{
private Recipe[] recipeList;
public RecipeManager(int maxNumOfElements)
{
Console.WriteLine("Recipe manager constructor called!");
recipeList = new Recipe[maxNumOfElements];
}
private int FindVacantPosition()
{
for (int i = 0; i < recipeList.Length; i++)
{
if (recipeList[i] == null)
{
Console.WriteLine("Found free position at: " + i);
return i;
}
}
return -1;
}
public bool CheckIndex(int index)
{
bool check = false;
if (index <= recipeList.Length && index >= 0)
{
check = true;
}
return check;
}
public Recipe GetRecipeAt(int index)
{
if (CheckIndex(index))
return recipeList[index];
else
return null;
}
public bool Add(Recipe newRecipe)
{
if (newRecipe == null)
return false;
bool ok;
int next = FindVacantPosition();
if (next >= 0)
{
ok = true;
Console.WriteLine("Setting recipe list at index " + next + " to " + newRecipe.ToString());
recipeList[next] = newRecipe;
}
else
{
Console.WriteLine("No space for recipe available! " + next);
ok = false;
}
return ok;
}
public int CurrentNumberofItems()
{
int num = 0;
for (int i = 0; i < recipeList.Length; i++)
{
if (recipeList[i] != null)
{
num++;
}
}
return num;
}
public string[] RecipeListToString()
{
string[] results = new string[recipeList.Length];
for (int i = 0; i < recipeList.Length; i++)
{
if (recipeList[i] != null)
results[i] = recipeList[i].ToString();
else
results[i] = string.Empty;
}
return results;
}
}
}
FormMain.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace programmingTask4
{
public partial class FormMain : Form
{
const int maxRecipe = 3;
const int maxIngredients = 20;
Recipe currRecipe = new Recipe(maxIngredients);
RecipeManager recipemanager = new RecipeManager(maxRecipe);
public FormMain()
{
Console.WriteLine("Form constructor was called!");
InitializeComponent();
InitializeGui();
}
public void InitializeGui()
{
comboBoxCategory.DataSource = Enum.GetValues(typeof(FoodCategory));
}
public void UpdateGUI()
{
//listBoxDisplay.Text = recipemanager.CurrentNumberofItems().ToString();
//listBoxDisplay.Text = currRecipe.Ingredient.ToString();
string[] recipeListStrings = recipemanager.RecipeListToString();
listBoxDisplay.Items.Clear();
listBoxDisplay.Items.AddRange(recipeListStrings);
}
private void buttonRecipe_Click(object sender, EventArgs e)//add recipe button
{
currRecipe.Category = (FoodCategory)comboBoxCategory.SelectedIndex;
currRecipe.Name = textBoxRecipeName.Text.Trim();
currRecipe.Description = richTextBoxDescription.Text.Trim();
Console.WriteLine("Adding recipe: " + currRecipe.ToString());
bool result = recipemanager.Add(currRecipe);
Console.WriteLine("Result was " + result + " for adding to recipe list");
UpdateGUI();
currRecipe.DefaultValues();
}
}
}
Recipe is a class, which mean it's a reference type.
In your main form, your currRecipe instance is never changed.
RecipeManager has an array to store references of instance but unfortunately it stores the same instance because of 2.
Since RecipeManager stores the same instance of currRecipe, any modification on currRecipe would display N times.
To prevent it. Modify your buttonRecipe_Click
private void buttonRecipe_Click(object sender, EventArgs e)//add recipe button
{
currRecipt = new Recipe(maxIngredients);
currRecipe.Category = (FoodCategory)comboBoxCategory.SelectedIndex;
currRecipe.Name = textBoxRecipeName.Text.Trim();
currRecipe.Description = richTextBoxDescription.Text.Trim();
Console.WriteLine("Adding recipe: " + currRecipe.ToString());
bool result = recipemanager.Add(currRecipe);
Console.WriteLine("Result was " + result + " for adding to recipe list");
UpdateGUI();
// No need to reset it, use new one everytime.
//currRecipe.DefaultValues();
}
I am confused as to exactly how classes inherit methods from each other. I already understand inheritance from base classes, there is however, certain code from an example that I do not understand. It involves searching a Binary tree and I could not find any resources that better explain how the code is inherited.
My aim is to understand it so that I can use it to also searched a linkedlist.
If any one can refer me to any relevant literature that explains this particular area I would be grateful.
I have highlighted the code section that I dont really yet understand how it is inhertied. The specific section is posted first:
public Company Read(string bezeichnung)
{
return stri.Search(new Company() { Bezeichnung = bezeichnung });
}
Entire program:
using System;
using System.IO;
using System.Text;
using System.Net;
namespace CompanySearch
{
class Program
{
static void Main(string[] args)
{
StreamReader r = new StreamReader(#"C:\Users\chris\Desktop\algo\fuckit\unternehmen.csv", Encoding.Default);
Companies stri2 = new Companies(r);
while (true)
{
Console.Write("Unternehmensbezeichnung eingeben: ");
string name = Console.ReadLine();
if (string.IsNullOrEmpty(name))
break;
//Company konk = stri2.Read(name);
Company konk = new Company();
konk = stri2.Read(name);
if (konk == null)
Console.WriteLine("Unternehmen nicht gefunden!");
else
Console.WriteLine(konk + "\n");
}
}
}
public class Companies
{
private BinaryTree<Company> stri = new BinaryTree<Company>();
public Companies(StreamReader rp)
{
// Spaltenüberschriften auslesen
//var tokens = rp.ReadLine().Split(new char[] { ';' });
//if (tokens.Length != 3)
// throw new ArgumentException("More than 3 columns in company file");
string line;
while ((line = rp.ReadLine()) != null)
{
var tokens = line.Split(new char[]{';'});
//tokens = line.Split(new char[] { ';' });
stri.Add(new Company()
{Bezeichnung = tokens[0], Branche = tokens[1], Ort = tokens[2]});
}
rp.Close();
}
public Company Read(string bezeichnung)
{
return stri.Search(new Company()
{Bezeichnung = bezeichnung});
}
}
public class Company : IComparable<Company>
{
public string Bezeichnung
{
get;
set;
}
public string Branche
{
get;
set;
}
public string Ort
{
get;
set;
}
public int CompareTo(Company other)
{
return Bezeichnung.CompareTo(other.Bezeichnung);
}
public override string ToString()
{
return string.Format("Bezeichnung: {0}\tBranche: {1}\tOrt: {2}", Bezeichnung, Branche, Ort);
}
}
public enum TraverseModeEnum
{
PreOrder,
PostOrder,
InOrder,
ReverseInOrder
}
public class BinaryTree<T>
where T : IComparable<T>
{
private sealed class Node<TNode>
where TNode : IComparable<TNode> // TNode muss IComparable implementieren
{
public TNode Item
{
get;
set;
}
public Node<TNode> Left
{
get;
set;
}
public Node<TNode> Right
{
get;
set;
}
public int CompareTo(TNode other)
{
return Item.CompareTo(other);
}
}
private Node<T> root;
public int Count
{
get;
private set;
}
public TraverseModeEnum TraverseMode
{
get;
set;
}
public BinaryTree()
{
TraverseMode = TraverseModeEnum.PreOrder;
}
public void Add(T item)
{
if (root == null)
root = new Node<T>()
{Item = item};
else
addTo(root, item);
Count++;
}
public void AddRange(T[] items)
{
foreach (var item in items)
Add(item);
}
private void addTo(Node<T> node, T item)
{
if (item.CompareTo(node.Item) < 0)
{
if (node.Left == null)
node.Left = new Node<T>()
{Item = item};
else
addTo(node.Left, item);
}
else
{
if (node.Right == null)
node.Right = new Node<T>()
{Item = item};
else
addTo(node.Right, item);
}
}
public bool Contains(T item)
{
Node<T> node = root;
while (node != null)
{
int c = node.Item.CompareTo(item);
if (c == 0)
return true;
if (c > 0)
node = node.Left;
else
node = node.Right;
}
return false;
}
public T Search(T item)
{
Node<T> node = root;
while (node != null)
{
int c = node.Item.CompareTo(item);
if (c == 0)
return node.Item;
if (c > 0)
node = node.Left;
else
node = node.Right;
}
return default (T);
}
public void Clear()
{
root = null;
Count = 0;
}
public override string ToString()
{
string s = "";
int level = 0;
traverse(root, level, ref s);
return s;
}
private void traverse(Node<T> node, int level, ref string s)
{
if (node == null)
return;
bool reverse = TraverseMode == TraverseModeEnum.ReverseInOrder;
if (TraverseMode == TraverseModeEnum.PreOrder)
s += "".PadLeft(level, ' ') + node.Item.ToString() + "\n";
traverse(reverse ? node.Right : node.Left, level + 2, ref s);
if (TraverseMode == TraverseModeEnum.InOrder || TraverseMode == TraverseModeEnum.ReverseInOrder)
s += "".PadLeft(level, ' ') + node.Item.ToString() + "\n";
traverse(reverse ? node.Left : node.Right, level + 2, ref s);
if (TraverseMode == TraverseModeEnum.PostOrder)
s += "".PadLeft(level, ' ') + node.Item.ToString() + "\n";
}
}
}
The class BinaryTree<T> down in the code demands that T must implement IComparable<T>. Lots of list-ish classes make similar demands. If a type implements IComparable<T> it means two instances of a class can be compared to each other with the ComparetTo( T t1, T t2 ) method. This method returns an indication of which T is greater than, less than, or equal to the other. Realize that the greater than, less than, or equal to is entirely up to the type that implements the interface. It's principally used for sorting or otherwise locating things in a tree, list, or other structure based on the comparison.
Implementing an interface looks like class inheritance. The syntax is the same...but it's more like a contract, since an interface has no code to inherit. If you make a class that goes like:
class MyClass: IComparable<MyClass>
{
//--> stuff
}
...then you're obligated to have a publicly visible method with the signature:
int CompareTo( MyClass a, MyClass b )
{
//--> look at the two instances and make a determination...
}
The method can use any characteristics of the class to determine what makes a greater than, less than, or equal to b...and thereby control how it's going to be placed into a structure.
A class can inherit from only one other class...but it can implement as many interfaces as it needs. This is what, I'm guessing, looks like multiple inheritance.
a. There is no real inheritance in your code. Only the implementation of a standard interface, IComparable<T>. Implementing an interface is sometimes called inheritance but it is not the same. In this case it forces Company to implement the CompareTo() method.
b. The code you have a question about just creates a temporary object. You can rewrite it to something that might be easier to understand:
//return stri.Search(new Company() { Bezeichnung = bezeichnung });
var tempCompany = new Company() { Bezeichnung = bezeichnung };
return stri.Search(tempCompany);
I have created custom linked list in c#.
LinkedList.cs:
class LinkedList
{
private Node Start;//Mazgas pr
private Node End;//Mazgas pb
private Node Current;// Mazas d saraso sasajai
public LinkedList()
{
this.Start = null;
this.End = null;
this.Current = null;
}
public Object Get(int index)
{
for( Node curr = Start; curr != null; curr = curr.Next)
{
if( curr.Index == index )
return curr.Data;
}
return null;
}
public void PrintData()
{
for (Node curr = Start; curr != null; curr = curr.Next)
{
Console.WriteLine("{0}: {1}", curr.Index, curr.Data);
}
}
public int Count()
{
int i = 0;
for( Node curr = Start; curr != null; curr = curr.Next, i++);
return i;
}
public void Add(Object data)
{
Node current = new Node(data, null);
if (Start != null)
{
End.Next = current;
End.Next.Index = End.Index + 1;
End = current;
}
else
{
Start = current;
End = current;
End.Index = 0;
}
}
}
Node.cs:
class Node
{
public Object Data { get; set; }
public Node Next { get; set; }
public int Index { get; set; }
public Node() { }
public Node(Object data, Node next )
{
Data = data;
Next = next;
}
public override string ToString ()
{
return string.Format ("Data: {0}", Data);
}
}
and Part.cs
class Part
{
public string Code { get; set; }
public string Name { get; set; }
public double Price { get; set; }
public Part(string code, string name, double price)
{
Code = code;
Name = name;
Price = price;
}
public Part() { }
public override string ToString()
{
return string.Format("{0} {1}", Name, Code);
}
}
Problem is, when i create list LinkedList parts = new LinkedList()
and add objects to it parts.Add(new Part("code", "name", 10)); i can't access Part object variables. I need to do this:
for( int i=0; i<parts.Count(); i++)
{
Console.WriteLine("{0}", (Part)Parts.Get(i).Name);
}
but it gives me error:
Error CS1061: Type 'object' does not contain a definition for 'Name'
and no extension method 'Name' of type 'object' could be found. Are
you missing an assembly reference? (CS1061)
EDITED: I need this linked list to be flexible for any type of object.
(Part)Parts.Get(i).Name is equivalent to (Part)(Parts.Get(i).Name) and since return value of your Get(i) is of type object and object doesn't have Name property, you received the exception.
You can correct it this way:
((Part)Parts.Get(i)).Name
Note:
I suppose it's just for learning purpose.
If all items of the list are of the same type, you can make your Generic classes. Having a generic Node<T> and LinkedList<T> class you can change the input parameters and return values to T instead of object.
In a real application, you can use LinkedList<T> or other generic data structures available.
I'm a java developer and new to C#, I'm stuck with InvalidCastException on the following code below.
I have implemented a Queue, based on a custom Doubly Linked List implementation. Both implementations are generic, and thus, on the test code, I want to use a generic print method.
The test code below is just working fine;
using System;
using System.Collections.Generic;
namespace Queue01
{
public class TestQueue
{
public static void Main(string[] args)
{
Queue<int> queue = new Queue<int>();
queue.Enqueue(4);
queue.Enqueue(5);
queue.Enqueue(6);
Console.WriteLine("*****");
PrintQueue(queue);
Console.WriteLine("*****");
int first = queue.Dequeue();
Console.WriteLine("Enqueued value : " + first);
Console.WriteLine("*****");
PrintQueue(queue);
}
public static void PrintQueue(object queue)
{
Queue<int> q = (Queue<int>)queue;
foreach (object i in q)
{
Console.WriteLine(i);
}
}
}
}
However, I want to make the PrintQueue static method working for all types, thus I've changed the method code as below;
public static void PrintQueue(object queue)
{
Queue<object> q = (Queue<object>)queue;
foreach (object i in q)
{
Console.WriteLine(i);
}
}
The whole test code which is not working is as below;
using System;
using System.Collections.Generic;
namespace Queue01
{
public class TestQueue
{
public static void Main(string[] args)
{
Queue<int> queue = new Queue<int>();
queue.Enqueue(4);
queue.Enqueue(5);
queue.Enqueue(6);
Console.WriteLine("*****");
PrintQueue(queue);
Console.WriteLine("*****");
int first = queue.Dequeue();
Console.WriteLine("Enqueued value : " + first);
Console.WriteLine("*****");
PrintQueue(queue);
}
public static void PrintQueue(object queue)
{
Queue<object> q = (Queue<object>)queue;
foreach (object i in q)
{
Console.WriteLine(i);
}
}
}
}
And then I'm stuck with the InvalidCastException. Where is the problem and how can I fix this exception and what is the best practice to make this code generic?
On java, Object is the base, root class of every class instance. Thus, I've passed the stack instance as an object to the method, assuming that it won't be a problem because int, the alias for Int32 also extended from the Object.
Here down below, I am adding the whole rest files that I've used for compiling the test code above;
1) Here is the DoublyLinkedListNode class that I used in Doubly Linked List implemetation;
using System;
using System.Collections.Generic;
namespace Queue01
{
public class DoublyLinkedListNode<T>
{
// Fields
public T Value { get; set; }
public DoublyLinkedListNode<T> Previous { get; set; }
public DoublyLinkedListNode<T> Next { get; set; }
public DoublyLinkedListNode(T value)
{
Value = value;
}
}
}
2) Here is my DoublyLinkedList class which implements a doubly linked list for the queue implementation I am going to use;
using System;
using System.Collections.Generic;
namespace Queue01
{
public class DoublyLinkedList<T> : ICollection<T>
{
#region Fields
public DoublyLinkedListNode<T> Head { get; private set; }
public DoublyLinkedListNode<T> Tail { get; private set; }
#endregion
#region Constructor
#endregion
#region Add
public void AddFirst(T value)
{
AddFirst(new DoublyLinkedListNode<T>(value));
}
public void AddFirst(DoublyLinkedListNode<T> node)
{
DoublyLinkedListNode<T> temp = Head;
Head = node;
Head.Next = temp;
//if(Count == 0)
if (Empty)
{
Tail = Head;
}
else
{
temp.Previous = Head;
}
Count++;
}
public void AddLast(T value)
{
AddLast(new DoublyLinkedListNode<T>(value));
}
public void AddLast(DoublyLinkedListNode<T> node)
{
//if (Count == 0)
if (Empty)
{
Head = node;
}
else
{
Tail.Next = node;
node.Previous = Tail;
}
Tail = node;
Count++;
}
#endregion
#region Remove
public void RemoveFirst()
{
//if (Count != 0)
if (!Empty)
{
Head = Head.Next;
Count--;
if (Count == 0)
{
Tail = null;
}
else
{
Head.Previous = null;
}
}
}
public void RemoveLast()
{
//if (Count != 0)
if (!Empty)
{
if (Count == 1)
{
Head = null;
Tail = null;
}
else
{
Tail.Previous.Next = null;
Tail = Tail.Previous;
}
Count--;
}
}
#endregion
#region ICollection
public int Count
{
get;
private set;
}
public void Add(T item)
{
AddFirst(item);
}
public bool Contains(T item)
{
DoublyLinkedListNode<T> current = Head;
while (current != null)
{
if (current.Value.Equals(item))
{
return true;
}
current = current.Next;
}
return false;
}
public void CopyTo(T[] array, int arrayIndex)
{
DoublyLinkedListNode<T> current = Head;
while (current != null)
{
array[arrayIndex++] = current.Value;
current = current.Next;
}
}
public bool IsReadOnly
{
get
{
return false;
}
}
public bool Remove(T item)
{
DoublyLinkedListNode<T> previous = null;
DoublyLinkedListNode<T> current = Head;
while (current != null)
{
if (current.Value.Equals(item))
{
if (previous != null)
{
previous.Next = current.Next;
if (current.Next == null)
{
Tail = previous;
}
else
{
current.Next.Previous = previous;
}
Count--;
}
else
{
RemoveFirst();
}
return true;
}
previous = current;
current = current.Next;
}
return false;
}
public void Clear()
{
Head = null;
Tail = null;
Count = 0;
}
//System.Collections.Generic.IEnumerator<T> System.Collections.Generic.IEnumerable<T>.GetEnumerator()
public IEnumerator<T> GetEnumerator()
{
DoublyLinkedListNode<T> current = Head;
while (current != null)
{
yield return current.Value;
current = current.Next;
}
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
//return ((System.Collections.Generic.IEnumerable<T>)this).GetEnumerator();
return this.GetEnumerator();
}
#endregion
#region helper
public void PrintEnumerable()
{
IEnumerator<T> e = this.GetEnumerator();
while (e.MoveNext())
{
T val = e.Current;
Console.WriteLine("Value: " + val);
}
}
public void PrintReverse()
{
for (DoublyLinkedListNode<T> node = Tail; node != null; node = node.Previous)
{
Console.WriteLine(node.Value);
}
}
public bool isEmpty()
{
if (Count == 0)
{
return true;
}
return false;
}
public bool Empty { get { return isEmpty(); } }
public DoublyLinkedListNode<T> First { get { return this.Head; } }
public DoublyLinkedListNode<T> Last { get { return this.Tail; } }
#endregion
}
}
3) And this is my Queue implementation based on doubly linked list implemetation that I've used above;
using System;
using System.Collections.Generic;
namespace Queue01
{
public class Queue<T> : System.Collections.Generic.IEnumerable<T>
{
DoublyLinkedList<T> _items = new DoublyLinkedList<T>();
LinkedList<T> hede = new LinkedList<T>();
public void Enqueue(T item)
{
_items.AddLast(item);
}
public T Dequeue()
{
if(_items.Count == 0)
{
throw new InvalidOperationException("The queue is empty.");
}
T value = _items.First.Value;
_items.RemoveFirst();
return value;
}
public IEnumerator<T> GetEnumerator()
{
return this._items.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
}
Fundamentally, you shouldn't try to make PrintQueue work for every object - you should try to make it work for any Queue<T>... and the simplest way of doing that is to make it generic:
public static void PrintQueue<T>(Queue<T> queue)
{
foreach (T item in queue)
{
Console.WriteLine(item);
}
}
Or you could be more general and accept an IEnumerable<T>:
public static void PrintSequence<T>(IEnumerable<T> queue)
{
foreach (T item in queue)
{
Console.WriteLine(item);
}
}
Your original code is failing because a Queue<int> isn't a Queue<object>... in fact, because Queue<T> isn't covariant in T, you can't convert Queue<string> to Queue<object>... but IEnumerable<T> is covariant, so:
Queue<string> stringQueue = new Queue<string>();
...
PrintSequence<object>(stringQueue);
... would be okay.
What about change PrintQueue method. Just like this:
public static void PrintQueue<T>(object queue)
{
var q = (Queue<T>)queue;
foreach (var i in q)
Console.WriteLine(i);
}
and use it like this:
PrintQueue<int>(queue);
change your code like this:
public static void PrintQueue(dynamic queue)
{
foreach (var i in queue)
{
Console.WriteLine(i);
}
}