C# Accessing a list from multiple methods - c#

I am looking to access a list from different methods in the same class.Is there an easier way to access the movieTitle list without making a new list for each method? Do I have to make a reference to the list in every method? or should I put them all into a separate class all together? My overall goal is to have a option menu that gets input from the user and depending on the input calls a method to list all movies, add a movie to the list, and pick a random movie from the list.
class Program
{
static void Main(string[] args)
{
optionMenu();
Console.Read();
}
static void optionMenu()
{
Console.Write("(a)LIST MOVIES|(b)ADD Movie|(c)RANDOM MOVIE");
string ui = Console.ReadLine();
if (ui == "a") { printNames(); }
else if (ui == "b") { addMovie(); }
else if (ui == "b") { randomPickMovie(); }
else { optionMenu(); }
}
static void printNames()
{
List<string> movieTitles = new List<string>();
/*list.....
/ movieTitles.Add("Jurassic Park");
/..........
/..........
*/..........
Console.WriteLine("Movies in your list...");
for (int i = 0; i < movieTitles.Count;i++)
{
Console.WriteLine("\t-" + movieTitles[i]);
}
}
static void addMovie()
{
Console.WriteLine("Enter a title:");
string newTitle = Console.ReadLine();
//I can't say...
//movieTitles.Add(newTitle);
//...? do I need to make an instance of the list?
}
static void randomPickMovie()
{
Random r = new Random();
int random = r.Next();
Console.WriteLine(movieTitle[random]);
//same here. How do I access the movie titles in the printName() method so
//I can randomly pick a movie from the list?
}
}

Below is one way make the movie list shared. This declares and initializes the list as a static member of the class (instead of a local variable in the methods).
This approach works well for simple programs, but having global state in a large program can be problematic because it becomes difficult to see which methods affect which global state so bugs can easily creep in. See below for another approach.
class Program
{
static void Main(string[] args)
{
...
}
static List<string> movieTitles = new List<string>();
static void optionMenu()
{
...
}
static void printNames()
{
Console.WriteLine("Movies in your list...");
for (int i = 0; i < movieTitles.Count;i++)
{
Console.WriteLine("\t-" + movieTitles[i]);
}
}
static void addMovie()
{
movieTitles.Add(newTitle);
}
static void randomPickMovie()
{
...
}
}
Another approach is to pass the data from one method to another. This makes it more obvious to see what methods use the movieList. It also allows us to specify additional restrictions, e.g. you can see that printNames only needs a read-only version of the list so you know that printNames can't modify the list. This approach is a little more work but it's a good habit to get into because it reduces bugs in the long term.
class Program
{
static void Main(string[] args)
{
...
}
static void optionMenu()
{
List<string> movieTitles = new List<string>();
string ui = Console.ReadLine();
if (ui == "a") { printNames(movieTitles); }
else if (ui == "b") { addMovie(movieTitles); }
else if (ui == "b") { randomPickMovie(movieTitles); }
else { optionMenu(); }
}
static void printNames(IReadOnlyList<string> movieTitles)
{
Console.WriteLine("Movies in your list...");
for (int i = 0; i < movieTitles.Count;i++)
{
Console.WriteLine("\t-" + movieTitles[i]);
}
}
static void addMovie(List<string> movieTitles)
{
movieTitles.Add(newTitle);
}
static void randomPickMovie(List<string> movieTitles)
{
...
}
}
See https://stackoverflow.com/questions/13295319/instance-field-vs-passing-method-parameter for another user's point of view on which approach is better.

as for me, I prefer doing it this way.
class Program
{
static void Main(string[] args)
{
Movie movie = new Movie();
int x = 0;
while (x < 1)
{
movie.optionMenu(); Console.Write("Do you want to exit?");
string response = Console.ReadLine();
if (response == "Y") { x = 1; }
}
Console.Read();
}
}
class Movie
{
public List<string> movieTitles { get; set; }
public Movie()
{
movieTitles = new List<string>();
}
public void optionMenu()
{
Console.Write("(a)LIST MOVIES|(b)ADD Movie|(c)RANDOM MOVIE");
string ui = Console.ReadLine();
if (ui == "a") { printNames(); }
else if (ui == "b") { addMovie(); }
else if (ui == "c") { randomPickMovie(); }
else { optionMenu(); }
}
public void printNames()
{
Console.WriteLine("Movies in your list...");
for (int i = 0; i < movieTitles.Count; i++)
{
Console.WriteLine("\t-" + movieTitles[i]);
}
}
public void addMovie()
{
Console.WriteLine("Enter a title:");
string newTitle = Console.ReadLine();
if (newTitle != "")
{
movieTitles.Add(newTitle);
Console.WriteLine("New movie successfully added!");
}
else
{
Console.WriteLine("Cannot add empty movie. Add movie failed.");
}
}
public void randomPickMovie()
{
if (movieTitles.Count != 0)
{
Random r = new Random();
int random = r.Next(0, movieTitles.Count - 1);
Console.WriteLine(movieTitles[random]);
}
else { Console.WriteLine("Movie list is empty."); }
}
}

Answer for all your questions is create MovieTitles property of type List<string> and access it like this:
class Program
{
static void Main(string[] args)
{
optionMenu();
Console.Read();
}
static List<string> movieTitles;
static List<string> MovieTitles
{
get
{
if (movieTitles == null)
CreateMoviesList();
return movieTitles;
}
}
static void CreateMoviesList()
{
movieTitles = new List<string>();
/*list.....
/ movieTitles.Add("Jurassic Park");
/..........
/..........
*/
}
static void optionMenu()
{
Console.Write("(a)LIST MOVIES|(b)ADD Movie|(c)RANDOM MOVIE");
string ui = Console.ReadLine();
if (ui == "a") { printNames(); }
else if (ui == "b") { addMovie(); }
else if (ui == "b") { randomPickMovie(); }
else { optionMenu(); }
}
static void printNames()
{
Console.WriteLine("Movies in your list...");
for (int i = 0; i < MovieTitles.Count; i++)
{
Console.WriteLine("\t-" + movieTitles[i]);
}
}
static void addMovie()
{
Console.WriteLine("Enter a title:");
string newTitle = Console.ReadLine();
MovieTitles.Add(newTitle);
}
static void randomPickMovie()
{
Random r = new Random();
int random = r.Next();
Console.WriteLine(MovieTitles[random]);
}
}
CreateMoviesList() create list of movies only once and can be use to print movies, randon pick and add movies later on.

Related

How to set default capacity for lists

So I tried making a todo list app making use of for loops and nested if statements. I created a function for adding tasks deleting and showing the whole list, but when I run the code I only get to input a task once even though I set the list capacity to what the user wants.
This is my code and what I've tried so far:
namespace mycsharpproject1
{
class Program
{
static void Main(string[] args)
{
List<string> todo = new List<string>();
void addt()
{
Console.WriteLine("enter task to be add");
todo.Add(Console.ReadLine());
}
void removet()
{
Console.WriteLine("enter task to be removed");
todo.Remove(Console.ReadLine());
}
void showt()
{
Console.WriteLine(todo);
}
string user_input = Console.ReadLine();
if (user_input == "r")
{
if (todo.Count == 0)
{
Console.WriteLine("you have no tasks in your list");
}
else
{
removet();
}
}
if (user_input == "a")
{
int i= Convert.ToInt32(Console.ReadLine());
if (i == todo.Capacity)
{
addt();
}
}
if (user_input == "s")
{
showt();
}
Console.ReadKey();
}
}
}
Modified your code a little bit. It's because there's no loop in your code, it only runs once. And the last like Console.ReadKey just reads an input and exits.
And the list doesn't need a capacity to be set if you exactly need that amount of item in yoru list. So, try this one.
class Program
{
static List<string> todo = null;
static void Main(string[] args)
{
todo = new List<string>();
while (true)
{
string user_input = Console.ReadLine();
if (user_input == "r")
{
if (todo.Count == 0)
{
Console.WriteLine("you have no tasks in your list");
}
else
{
removet();
}
}
if (user_input == "a")
{
addt();
}
if (user_input == "s")
{
showt();
}
}
}
static void addt()
{
Console.WriteLine("enter task to be add");
todo.Add(Console.ReadLine());
}
static void removet()
{
Console.WriteLine("enter task to be removed");
todo.Remove(Console.ReadLine());
}
static void showt()
{
todo.ForEach(q => Console.WriteLine(q));
}
}

Passing two 2dimensional arrays to method one after the other, C#

I want to run my Sudoku checker (written in method CheckSudokuSolution on the bottom) with two sudoku solutions.
i'm not very experienced in passing parameters and although my research cannot do that:
I need to pass to method CheckSudokuSolution first my 1. Sudoku (in Solution1) and then the second (in Solution2).
Should I change something with the Solution1(), Solution2()?
If you have time for explainment, I would be happy. Thanks.
My program:
static void Main(string[] args)
{
CheckSudokuSolution(s);
CheckSudokuSolution(s);
Console.ReadKey(true);
}
static void Solution1()
{
int[,] s = new int[,]
{
{ 4,3,5,2,6,9,7,8,1},
{ 6,8,2,5,7,1,4,9,3},
{ 1,9,7,8,3,4,5,6,2},
{ 8,2,6,1,9,5,3,4,7},
{ 3,7,4,6,8,2,9,1,5},
{ 9,5,1,7,4,3,6,2,8},
{ 5,1,9,3,2,6,8,7,4},
{ 2,4,8,9,5,7,1,3,6},
{ 7,6,3,4,1,8,2,5,9}
};
}
static void Solution2()
{
int[,] s = new int[,]
{
{ 1,5,2,4,8,9,3,7,6},
{ 7,3,9,2,5,6,8,4,1},
{ 4,6,8,3,7,1,2,9,5},
{ 3,8,7,1,2,4,6,5,9},
{ 5,9,1,7,6,3,4,2,8},
{ 2,4,6,8,9,5,7,1,3},
{ 9,1,4,6,3,7,5,8,7},
{ 6,2,5,9,4,8,1,3,7},
{ 8,7,3,5,1,2,9,6,4}
};
}
static void CheckSudokuSolution(int[,] s )
{
// code
}
In Main(), you have no variable named s, so you get an error with what you currently have. I suggest making Solution1 a static variable instead of a function:
static int[,] Solution1 = new int[,]
{
{ 4,3,5,2,6,9,7,8,1},
{ 6,8,2,5,7,1,4,9,3},
{ 1,9,7,8,3,4,5,6,2},
{ 8,2,6,1,9,5,3,4,7},
{ 3,7,4,6,8,2,9,1,5},
{ 9,5,1,7,4,3,6,2,8},
{ 5,1,9,3,2,6,8,7,4},
{ 2,4,8,9,5,7,1,3,6},
{ 7,6,3,4,1,8,2,5,9}
};
Now you can pass it in directly:
CheckSudokuSolution(Solution1);
Similarly for Solution2.
Not sure to get the all point there but you can use class in first place to see your arrays from the main then :
Send your arrays to CheckSudokuSolution().
Check the return value.
Exemple :
static void Main(string[] args)
{
int[,] s1 = CheckSudokuSolution(Solutions.s1);
int[,] s2 = CheckSudokuSolution(Solutions.s2);
// display sudoku s1
int i = 0;
foreach (var item in s1)
{
if (i == 9)
{
Console.WriteLine();
i = 0;
}
Console.Write(item.ToString());
i++;
}
Console.ReadKey(true);
}
public static class Solutions
{
public static int[,] s1 = new int[,]
{
{ 4,3,5,2,6,9,7,8,1},
{ 6,8,2,5,7,1,4,9,3},
{ 1,9,7,8,3,4,5,6,2},
{ 8,2,6,1,9,5,3,4,7},
{ 3,7,4,6,8,2,9,1,5},
{ 9,5,1,7,4,3,6,2,8},
{ 5,1,9,3,2,6,8,7,4},
{ 2,4,8,9,5,7,1,3,6},
{ 7,6,3,4,1,8,2,5,9}
};
public static int[,] s2 = new int[,]
{
{ 1,5,2,4,8,9,3,7,6},
{ 7,3,9,2,5,6,8,4,1},
{ 4,6,8,3,7,1,2,9,5},
{ 3,8,7,1,2,4,6,5,9},
{ 5,9,1,7,6,3,4,2,8},
{ 2,4,6,8,9,5,7,1,3},
{ 9,1,4,6,3,7,5,8,7},
{ 6,2,5,9,4,8,1,3,7},
{ 8,7,3,5,1,2,9,6,4}
};
}
static int[,] CheckSudokuSolution(int[,] s)
{
// Do something with s
return s;
}
}

Reference to public static queue of static class gets lost

I have a static class A which has a public static ConcurrentQueue.
This class has a method which calls a method of another static class B.
In this method of static class B, a worker thread is started which polls for items in the static ConcurrentQueue of class A. If found, it dequeues the item and processes it.
The same method in class B also starts another thread which checks if the queue of class A is being constantly filled. If the filling occasionally is somehow stuck, a call to a static method in class A is made which resets and restarts the process.
And here comes the problem: When I restart the filling, items are inserted again into the static queue of static class A. But my thread in static class B which checks for items in the queue does not find any items anymore.
So my idea is that in class B I somehow lost the reference to the original static queue of class A. I think I oversee here some principles of static classes, but can not figure out what exactly.
EDIT: Here are some more details.
Main:
public static void Main(string[] args)
{
B.Initialize(8);
A.StartDataStream();
Console.ReadKey();
}
Class A:
class A
{
private static ACOMObject MyCOMObjekt;
public static ConcurrentQueue<PriceItem> Prices = new ConcurrentQueue<PriceItem>();
public static void StartDataStream()
{
DataStream myDataStream = GetDataStream();
FillStream(myDataStream);
B.StartHeartbeatCheck();
Console.WriteLine("Press Key to Exit Stream Call.");
Console.ReadKey();
GC.KeepAlive(myDataStream);
GC.KeepAlive(MyCOMObjekt);
}
private static DataStream GetDataStream()
{
if (MyCOMObjekt== null)
{
MyCOMObjekt= new ACOMObject ();
}
return (DataStream) MyCOMObjekt.DataStream;
}
private static void FillStream(DataStream myDataStream)
{
foreach (var symbol in Symbols.SymbolList)
{
myDataStream.Add(symbolNr, 1);
}
myDataStream.Bid += new _IDataStreamEvents_BidEventHandler(myDataStream_Bid);
myDataStream.Ask += new _IDataStreamEvents_AskEventHandler(myDataStream_Ask);
}
private static void myDataStream_Bid(int SymbolNr, float Price, DateTime Time)
{
PriceItem p;
p.SymbolNr = SymbolNr;
p.Price = Price;
p.Time = Time;
p.IsBid = true;
Prices.Enqueue(p);
}
private static void myDataStream_Ask(int SymbolNr, float Price, DateTime Time)
{
PriceItem p;
p.SymbolNr = SymbolNr;
p.Price = Kurs;
p.Time = Zeit;
p.IsBid = false;
Prices.Enqueue(p);
}
public static void RestartMyCOMProcess()
{
try
{
Process proc = Process.GetProcessesByName("MyCOMProcess")[0];
proc.Kill();
}
catch (Exception)
{
//No Process = fine
}
MyCOMObjekt = null;
DataStream myDataStream = GetDataStream();
myDataStream.Bid -= new _IDataStreamEvents_BidEventHandler(myDataStream_Bid); //probably not necessary...
myDataStream.Ask -= new _IDataStreamEvents_AskEventHandler(myDataStream_Ask); //probably not necessary...
FillStream(myDataStream);
}
}
Class B:
class B
{
private static int countPrices; //Incremented every time a price is taken out of Price Queue
public static void Initialize(int numberOfWorkerThreads)
{
StartWorkers(numberOfWorkerThreads);
}
public static void StartWorkers(int number)
{
for (int j = 0; j < number; j++)
{
Thread t = new Thread(ScanForPrices);
t.Name = "ScanForPrices" + j;
t.Start();
}
}
private static void ScanForPrices()
{
try
{
while (true)
{
PriceItem p;
if (A.Prices.TryDequeue(out p))
{
if (p.IsBid)
{
AnalyzeBidPrice(p);
}
else
{
HandleAskPrice(p);
}
Interlocked.Increment(ref countPrices)
}
else
{
Thread.Sleep(1);
}
}
}
catch (ThreadAbortException)
{
Console.WriteLine("Price Scan Thread aborted.");
}
}
public static void StartHeartbeatCheck()
{
Thread t = new Thread(CheckHeartBeat);
t.Name = "CheckHeartBeat";
t.Start();
}
private static void CheckHeartBeat()
{
TimeSpan start = new TimeSpan(09, 0, 0); //09 o'clock
TimeSpan end = new TimeSpan(20, 0, 0); //20 o'clock
TimeSpan stopTime = new TimeSpan(20, 5, 0); //20 o'clock and 5 minutes
int countSuccessiveBlockings = 0;
try
{
while (true)
{
Thread.Sleep(5000);
TimeSpan now = DateTime.Now.TimeOfDay;
if ((now > start) && (now < end))
{
int countOld = countPrices;
Thread.Sleep(1000);
if (countOld == countPrices)
{
Console.WriteLine(DateTime.Now + ": Price Stream blocked!");
countSuccessiveBlockings++;
}
else
{
countSuccessiveBlockings = 0;
}
if (countSuccessiveBlockings > 2)
{
A.RestartMyCOMProcess();
countSuccessiveBlockings = 0;
}
}
}
}
catch (ThreadAbortException)
{
Console.WriteLine("Heartbeat Thread aborted.");
}
}
}

Queue items missing

I have a class with 2 queues - a and b.
When I insert values to the second queue(queue b) all values from the first one(queue a) are being removed.
Here is part of the class:
class SuperMarket
{
private Queue<string> a;
private Queue<string> b;
public SuperMarket()
{
this.a = new Queue<string>();
this.b = new Queue<string>();
}
public void InsertToA(string name)
{
this.a.Insert(name);
}
public void InsertToB(string name)
{
this.b.Insert(name);
}
this is the main program:
public static void Main(string[] args)
{
SuperMarket a = new SuperMarket();
Console.WriteLine("Enter Names For first");
string name = Console.ReadLine();
while (name.CompareTo("aaa") != 0)
{
a.InsertToA(name);
name = Console.ReadLine();
}
Console.WriteLine("Enter Names For second");
name = Console.ReadLine();
while (name.CompareTo("aaa") != 0)
{
a.InsertToB(name);
name = Console.ReadLine();
}
}
What might cause this effect?
Thank you very much!
After a few years later, I can easily answer my own question:
public void InsertToA(string name)
{
this.a.Enqueue(name);
}
public void InsertToB(string name)
{
this.b.Enqueue(name);
}
--> One should use Enqueue instead of Insert when working with generics in c#.

See any problems with this C# implementation of a stack?

I wrote this quickly under interview conditions, I wanted to post it to the community to possibly see if there was a better/faster/cleaner way to go about it. How could this be optimized?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Stack
{
class StackElement<T>
{
public T Data { get; set; }
public StackElement<T> Below { get; set; }
public StackElement(T data)
{
Data = data;
}
}
public class Stack<T>
{
private StackElement<T> top;
public void Push(T item)
{
StackElement<T> temp;
if (top == null)
{
top = new StackElement<T>(item);
}
else
{
temp = top;
top = new StackElement<T>(item);
top.Below = temp;
}
}
public T Pop()
{
if (top == null)
{
throw new Exception("Sorry, nothing on the stack");
}
else
{
T temp = top.Data;
top = top.Below;
return temp;
}
}
public void Clear()
{
while (top != null)
Pop();
}
}
class TestProgram
{
static void Main(string[] args)
{
Test1();
Test2();
Test3();
}
private static void Test1()
{
Stack<string> myStack = new Stack<string>();
myStack.Push("joe");
myStack.Push("mike");
myStack.Push("adam");
if (myStack.Pop() != "adam") { throw new Exception("fail"); }
if (myStack.Pop() != "mike") { throw new Exception("fail"); }
if (myStack.Pop() != "joe") { throw new Exception("fail"); }
}
private static void Test3()
{
Stack<string> myStack = new Stack<string>();
myStack.Push("joe");
myStack.Push("mike");
myStack.Push("adam");
myStack.Clear();
try
{
myStack.Pop();
}
catch (Exception ex)
{
return;
}
throw new Exception("fail");
}
private static void Test2()
{
Stack<string> myStack = new Stack<string>();
myStack.Push("joe");
myStack.Push("mike");
myStack.Push("adam");
if (myStack.Pop() != "adam") { throw new Exception("fail"); }
myStack.Push("alien");
myStack.Push("nation");
if (myStack.Pop() != "nation") { throw new Exception("fail"); }
if (myStack.Pop() != "alien") { throw new Exception("fail"); }
}
}
}
I think the Clear() method could be sped up significantly by changing it to top = null;. The entire stack will be garbage collected, and no loop required in the mean time.
You could simply use an array. The .NET array methods are really fast.
public class Stack<T>
{
private const int _defaultSize = 4;
private const int _growthMultiplier = 2;
private T[] _elements;
private int _index;
private int _limit;
public Stack()
{
_elements = new T[_defaultSize];
_index = -1;
_limit = _elements.Length - 1;
}
public void Push(T item)
{
if (_index == _limit)
{
var temp = _elements;
_elements = new T[_elements.Length * _growthMultiplier];
_limit = _elements.Length - 1;
Array.Copy(temp, _elements, temp.Length);
}
_elements[++_index] = item;
}
public T Pop()
{
if (_index < 0)
throw new InvalidOperationException();
var item = _elements[_index];
_elements[_index--] = default(T);
return item;
}
public void Clear()
{
_index = -1;
Array.Clear(_elements, 0, _elements.Length);
}
}
Might be preferable to use dynamic array as the data structure instead of a linked list. The array will have better locality of reference because the elements are next to each other. A stack doesn't need ability to delete elements in the middle, splicing etc. so an array suffices.

Categories

Resources