Linkedlist Using Solid Principles-C# - c#

I have my code for linked list here I have attached below, In this all methods are declared in a single class, now I am refactoring my code so I am moving my methods to separate class, after moving my data to separate class my data is not getting passed which so my data is not getting displayed, I think my way of passing the data through the variables to other classes is where the problem occurs, I don't know how to rectify this..here I have attached my code..
here is my code:
//My node class:
public class Node
{
public int info;
public Node link;
public Node(int i)
{
info = i;
link = null;
}
}
// My class to print the data:
public class Display
{
public void DispalyList()//list to display the items
{
Node p;
SingleLinkedList lst = new SingleLinkedList();
if (lst.start == null) // I have a doubt whether calling the start variable using that object is not correct., If data is being passed here I can proceed further
{
Console.WriteLine("List is empty");
return;
}
Console.Write("list is: ");
p = lst.start; //The way of calling the start object is wrong I guess
while (p != null) // p value is null here
{
Console.Write(p.info + " ");
p = p.link;
}
Console.WriteLine();
}
}
// My Single Linked list class://for time being i have two methods in this class
public class SingleLinkedList
{
public Node start;
public SingleLinkedList()//constructor
{
start = null;
}
public void CreateList() //Method where I am inserting the data
{
int i, n, data;//variable declaration
Console.Write("enter the number of nodes");
n = Convert.ToInt32(Console.ReadLine());
if (n == 0)
return;
for (i = 1; i <= n; i++)
{
Console.WriteLine("enter the element to be inserted");
data = Convert.ToInt32(Console.ReadLine());
InsertAtEnd(data);
}
}
public void InsertAtEnd(int data)//Method to insert the data into the list
{
Node p;
Node temp = new Node(data);
if (start == null)
{
start = temp;
return;
}
p = start;
while (p.link != null)
p = p.link;
p.link = temp;
}
}
}
//Main class using switch case:// I am just calling the display method alone for time being
public class Program
{
static void Main(string[] args)//Main program calling the methods
{
int choice;
SingleLinkedList list = new SingleLinkedList();
list.CreateList();// calling the createlist method
while (true)
{
Console.WriteLine("1.Display List");
Console.WriteLine("Enter your choice");
choice = Convert.ToInt32(Console.ReadLine());
if (choice == 13) //I have 13 cases for time being I have shown only one below
break;
switch(choice)//Switch case calling the methods
{
case 1:
Display dis = new Display();
dis.DispalyList();//calling display method which prints the data
break;
default://default case
Console.WriteLine("Wrong Choice");
}
}
}
}
Here is my above code, in which the value of the start in the[ DisplayList()] method is assigning null.If the data is being passed to it in this method i can follow the same for my other classes too. I don't know how to assign the data here..

I would suggest using ReadAllLines() instead, which will return a collection of strings, one per line in your input:
public class ReadingTextFile: IReadingTextFile {
public IEnumerable<string> content() { // change the return type
string path = # "C:\Users\s\Desktop\Datas\Data Input.txt";
var data = File.ReadAllLines(path); // and this
return data;
}
}
Then you can either just use the file.content() if all you need is a list:
IReadingTextFile file = new ReadingTextFile();
LinkedList < string > data = new LinkedList < string > ();
IEnumerable<string> inp = file.content(); // this is a collection of strings, one per line of your input
// ...
Or if you still want a linked list, you can just use the LinkedList constructor that takes a collection:
public class Readingtolist {
public void Input() {
IReadingTextFile file = new ReadingTextFile();
Stopwatch sw = new Stopwatch();
sw.Start();
IEnumerable<string> inp = file.content(); // the reading the file is probably what you really want to time.
sw.Stop();
var data = new LinkedList<string>(inp); // note the use of (inp) here
Console.Write("\n time Taken For Read Data: {0} ms",
sw.Elapsed.TotalMilliseconds);
Console.WriteLine("\n The items are{0}", inp);
}
}

Related

How to LINQ-ify the following loop?

I have a method in a C# program. It enumerates all the .cs files in a certain folder and then runs through the list. For each file, I read all the lines using File.ReadAllLines on it. I only want to process a file if it contains a class, whether conventional, static, or abstract, whose name begins with a certain phrase and does not end with the word Tests. Moreover, I wish to find the line index in the line of lines containing the declaration of the class --- i.e., the public static class Foo part.
Given that I take the result of File.ReadAllLines and call ToList() on it to create a List<string>, I wish to use the FindIndex method to find the index of the line matching my criteria (if it exists) using a Predicate.
My question is: What is a good way to write such a predicate?
I realize I could probably use more sophisticated methods, but I am just putting this code into a quick-and-dirty LINQPad script. So, I don't have to get super fancy.
Let me show you what I have so far (assume that the outermost namespace and class are already suitably declared):
void Main()
{
var files = Directory
.EnumerateDirectories(
Path.Combine(
Environment.GetFolderPath(
Environment.SpecialFolder.UserProfile
), #"source\repos\astrohart\MFR"
), "*", SearchOption.TopDirectoryOnly
).SelectMany(
x => Directory.EnumerateFiles(
x, "FileSystemEntry*.cs", SearchOption.AllDirectories
)
)
.Where(x => !"FileSystemEntry.cs".Equals(Path.GetFileName(x)))
.ToList();
if (files == null || !files.Any()) return;
foreach (var file in files)
{
var contents = string.Empty;
try
{
contents = File.ReadAllText(file);
}
catch (Exception ex)
{
Console.WriteLine($"ERROR: {ex.Message}");
contents = string.Empty;
}
if (string.IsNullOrWhiteSpace(contents)) continue;
if (contents.Contains("[TestFixture]")) continue;
if (contents.Contains("[Log(AttributeExclude = true)]")) continue;
file.Dump();
var lines = new List<string>();
lines.TrimExcess();
try
{
lines = File.ReadAllLines(file).ToList();
}
catch (Exception ex)
{
Console.WriteLine($"ERROR: {ex.Message}");
lines = new List<string>();
lines.TrimExcess();
}
if (lines == null || !lines.Any()) continue;
var index = -1;
for (var i = 0; i < lines.Count; i++)
{
var currentLine = lines[i].Trim();
if (currentLine.EndsWith("Tests")) continue;
if (currentLine.StartsWith("public static class FileSystemEntry"))
{
index = i;
break;
}
if (currentLine.StartsWith("public class FileSystemEntry"))
{
index = i;
break;
}
if (currentLine.StartsWith("public abstract class FileSystemEntry"))
{
index = i;
break;
}
}
if (index < 0) continue;
/*...*/
}
}
How do I translate the for loop in:
var index = -1;
for (var i = 0; i < lines.Count; i++)
{
var currentLine = lines[i].Trim();
if (currentLine.EndsWith("Tests")) continue;
if (currentLine.StartsWith("public static class FileSystemEntry"))
{
index = i;
break;
}
if (currentLine.StartsWith("public class FileSystemEntry"))
{
index = i;
break;
}
if (currentLine.StartsWith("public abstract class FileSystemEntry"))
{
index = i;
break;
}
}
if (index < 0) continue;
into a call thus:
var index = lines.FindIndex(currentLine => /*...*/);
I need help with how to derive the proper body of the lambda expression that matches what the for loop does.
Thanks in advance!
EDIT 1
I squinted my eyes at my loop just a little more. I am looking for a predicate to use specifically with the FindIndex method. I thought a little harder and I figured out maybe I can get away with:
var index = lines.FindIndex(currentLine => !currentLine.Trim.EndsWith("Tests") && currentLine.Trim().StartsWith("public static class FileSystemEntry") || currentLine.Trim().StartsWith("public class FileSystemEntry") || currentLine.Trim().StartsWith("public abstract class FileSystemEntry"));
Perhaps I can implement an extension method
public static bool StartsWithAnyOf(this string value, params string[] testStrings)
{
var result = false;
try
{
if (string.IsNullOrWhiteSpace(value.Trim())) return result;
if (testStrings == null || !testStrings.Any()) return result;
foreach(var element in testStrings)
if (value.Trim().StartsWith(element))
{
result = true;
break;
}
}
catch
{
result = false;
}
return result;
}
Then I'd declare another method:
public static bool KeepLine(string currentLine)
{
if (string.IsNullOrWhiteSpace(currentLine.Trim())) return false;
if (currentLine.Trim().EndsWith("Tests")) return false;
return currentLine.StartsWithAnyOf(
"public static class FileSystemEntry",
"public class FileSystemEntry",
"public abstract FileSystemEntry"
);
}
Then use it thus:
var index = lines.FindIndex(KeepLine);
Would that work?
I havent tested this thoroughly but it seems to pass basic sanity if I compare to original code supplied above. Note that this is not best when it comes to measuring performance. The 'foreach' loop with anonymous function has flaw that you cannot break away from the anonymous function. The only way to come out of a foreach is to run all foreach statements. In order to preserve first index where criteria matches against line contents, I am using index in else if() comparison statement. This means the foreach loop will run for all lines despite of having the first occurrence of matching lines found.
lines.ForEach((l) =>
{
if (l.EndsWith("Tests")) ;
else if (index ==0 && (l.StartsWith("public static class FileSystemEntry") ||
l.StartsWith("public class FileSystemEntry") ||
l.StartsWith("public abstract class FileSystemEntry")))
{
index = lines.IndexOf(l);
}
});

How to unit test code that requires user input c#

its my first time doing unit tests/integration tests and I have a question. So I started doing unit tests for my code, but I have a method, which is actually the logic of the whole application, where multiple methods are called, and user input is required. How can I test that method? Here is the method:
public async Task RunAsync()
{
var watch = System.Diagnostics.Stopwatch.StartNew();
var playAgain = 'y';
do
{
var attempts = 1;
var foundNumber = false;
while (attempts < 10 && foundNumber == false)
{
try
{
var inputNumber = int.Parse(GetInput());
if (inputNumber == _randomNumber)
{
foundNumber = true;
OnSuccesfulGuess(watch, attempts);
}
else if (attempts < 10)
{
OnWrongGuessWithinAttempts(inputNumber);
}
else
{
Console.WriteLine("Oops, maybe next time.");
}
}
catch (Exception ex)
{
Console.WriteLine("Please enter a number");
}
attempts++;
}
playAgain = PlayAgain(playAgain);
_randomNumber = await GetRandomNumber(1, 100);
Log.Information("User wants to play again");
}
while (playAgain == 'y' || playAgain == 'Y');
}
This is the method where i run in my Program class in order to start the application.
Your code is essentially untestable.
The method does too much work. It should be splitted into several smaller ones that can be tested separately.
You should get rid of static methods. Because you can't get them fake.
Getting data over the network (I see using WebSocket), as well as from the database or file system, should be brought out. You should pass ready-made data to this method.
Here is the modified code, broken down into small methods. Logging and events are removed from the code so as not to complicate the explanation.
public class App
{
private readonly Random _random = new Random();
private Task<int> GetRandomNumber(int min, int max)
{
return Task.FromResult(_random.Next(min, max));
}
internal int GetInput()
{
Console.WriteLine("Please guess a number between 1 and 100");
int value;
while (true)
{
string input = Console.ReadLine();
bool result = int.TryParse(input, out value);
if (!result)
Console.WriteLine("Not a number");
else if (value < 1 || value > 100)
Console.WriteLine("Must be between 1 and 100");
else
break;
}
return value;
}
internal bool PlayAgain()
{
Console.WriteLine("Do you want to play again?");
string input = Console.ReadLine();
return input == "Y" || input == "y";
}
internal void Guessing(int randomNumber)
{
int attempts = 1;
while (attempts < 10)
{
var inputNumber = GetInput();
// logging
if (inputNumber == randomNumber)
{
// OnSuccesfulGuess
return;
}
else
{
// OnWrongGuessWithinAttempts
}
attempts++;
}
Console.WriteLine("Oops, maybe next time.");
// logging
}
public async Task RunAsync()
{
do
{
int randomNumber = await GetRandomNumber(1, 100);
Guessing(randomNumber);
}
while (PlayAgain());
}
}
Now we have the ability to test individual methods.
I use MSTest.
[DataTestMethod]
[DataRow("Y")]
[DataRow("y")]
public void PlayAgain_InputY_ReturnsTrue(string value)
{
using (var reader = new StringReader(value))
{
Console.SetIn(reader);
var app = new App();
bool result = app.PlayAgain();
Assert.IsTrue(result);
}
}
[DataTestMethod]
[DataRow("N")]
[DataRow("boo")]
[DataRow("")]
public void PlayAgain_InputNotY_ReturnsFalse(string value)
{
using (var reader = new StringReader(value))
{
Console.SetIn(reader);
var app = new App();
bool result = app.PlayAgain();
Assert.IsFalse(result);
}
}
We do the same with the other methods.
Here are the tests for the GetInput method.
Since there is a loop inside that runs indefinitely when incorrect values are entered, we must interrupt it by entering the correct value. This is done by passing two values via a line feed: "0\n50". Entering an incorrect value is a test of the output string, then interrupting the loop with the correct value.
[DataTestMethod]
[DataRow("1")]
[DataRow("50")]
[DataRow("100")]
public void GetInput_InputCorrectString_ReturnsNumber(string value)
{
using (var reader = new StringReader(value))
{
Console.SetIn(reader);
var app = new App();
int actual = app.GetInput();
int expected = int.Parse(value);
Assert.AreEqual(expected, actual);
}
}
[DataTestMethod]
[DataRow("0\n50")]
[DataRow("101\n50")]
public void GetInput_InputSmallerOrGreaterValue_WritesMessage(string value)
{
using (var reader = new StringReader(value))
using (var writer = new StringWriter())
{
Console.SetIn(reader);
Console.SetOut(writer);
var app = new App();
_ = app.GetInput();
string actualMessage = writer.ToString();
string expectedMessage = "Must be between 1 and 100";
Assert.IsTrue(actualMessage.Contains(expectedMessage));
}
}
[DataTestMethod]
[DataRow("x\n50")]
[DataRow("qwerty\n50")]
public void GetInput_InputNotNumber_WritesMessage(string value)
{
using (var reader = new StringReader(value))
using (var writer = new StringWriter())
{
Console.SetIn(reader);
Console.SetOut(writer);
var app = new App();
_ = app.GetInput();
string actualMessage = writer.ToString();
string expectedMessage = "Not a number";
Assert.IsTrue(actualMessage.Contains(expectedMessage));
}
}
Normally the unit testing methods are made regarding the different results that may return. You can create an interface to handle this method and communicate giving values depending of the output expected (Mocking). Check this post maybe would help!:
How do I apply unit testing to C# function which requires user input dynamically?

Calling non static inside static main C#

I'm new to C# and programming all together and am trying to get this to run. I have spent the entire day reading about Static and non Static and cant seem to get it right. Any and all help would be appreciated as I need this code working by tomorrow evening. The following is the Main and Course Class:
using System;
namespace Lab4
{
class MainClass
{
public static void Main (string[] args)
{
Console.WriteLine ("Welcome to the Course Monitoring System v1.0");
Course.Menu ();
Course.Choice ();
}
}
}
This is the Course Class:
using System;
using System.Collections.Generic;
namespace Lab4
{
public class Course
{
private string courseNumber;
private string courseName;
private int courseHours;
private string descript;
private string prefix;
public List<Course> school = new List<Course> ();
private int howmany=0;
private int totalcourse=0;
//This section is for returning and adjusting values of private data through the main program.
public string cn{
get {return courseNumber; }
set {if (value != null)
cn = value;
}
}
public string name{
get{ return courseName; }
set{if (value!="")
name=courseName;
}
}
public int hours{
get {return courseHours; }
set {if (value != 0)
hours = value;
}
}
public string script {
get {return descript; }
set {
if (value != "")
script = value;
}
}
public string pfix {
get {return prefix; }
set {if (value != "")
pfix = value;
}
}
public Course (string pfix, string name, string cn, int hours, string script)
{
courseNumber = cn;
courseName = name;
courseHours = hours;
descript= script;
prefix = pfix;
}
//This portion of code overrides the string and allows it to output the information held within the constructor.
public override string ToString ()
{
return prefix + " " + courseName+" " + courseNumber + " " + descript + " It is a " + courseHours + " hour course.";
}
//The menu application for my program
public static void Menu()
{
Console.WriteLine ("Please choose from one of the following options: ");
Console.WriteLine ("......................................................................");
Console.WriteLine ("1.)Start a new Course List.");
Console.WriteLine ("2.)Delete Course from Current List.");
Console.WriteLine ("3.)Print Current Course List.");
Console.WriteLine ("4.)Add Course to Current List.");
Console.WriteLine ("5.)Shutdown Program");
}
//This is the controller for the menu. It allows for functionality to control the tasks requested by the user.
public void Choice()
{
int selection=int.Parse(Console.ReadLine());
while (selection >5 || selection < 1) {
Console.WriteLine ("Choice invalid. Please choose between 1 and 5.");
selection = int.Parse (Console.ReadLine ());
}
if (selection == 4) {
Add ();
Menu ();
Choice ();
Console.WriteLine ();
}
if (selection == 2) {
Delete ();
Menu ();
Choice ();
Console.WriteLine ();
}
if (selection == 3) {
Print ();
Menu ();
Choice ();
Console.WriteLine ();
}
if (selection == 1) {
New ();
Menu ();
Choice ();
Console.WriteLine ();
}
if (selection == 5) {
Console.WriteLine ();
Console.WriteLine ("Thank you for using this program for your scheduling needs.");
}
}
//This method when called will print a numbered list of courses refrenced by the created List
public void Print()
{
Console.WriteLine ();
Console.WriteLine ("Course Name.........Course Number.........Course Description........Course Hours");
Console.WriteLine ("********************************************************************************");
for (int i = 0; i < totalcourse; i++) {
int place = i + 1;
Console.WriteLine (place+".)"+school [i]);
}
Console.WriteLine ();
}
//This method will add an item to the end of the current list.
public void Add()
{
Console.WriteLine ();
Console.Write ("How many courses would you like to add at the end of your index?");
int numberAdded = int.Parse(Console.ReadLine ());
for (int i = 0; i < numberAdded; i++) {
Console.WriteLine ("Please use the following templet for your entries...");
Console.WriteLine ("Course Prefix, Course Name, Course Number, Course Hours, Course Description ");
school.Add (new Course (prefix = Console.ReadLine (), courseName = Console.ReadLine (),
courseNumber = Console.ReadLine (), courseHours = int.Parse (Console.ReadLine ()), descript = Console.ReadLine ()));
}
totalcourse = totalcourse + numberAdded;
Console.WriteLine ();
}
//This method will delete an Item from the list based on the position 0-x based on x-1, the output that is seen by the user. After each iteration it will
//also create a list so that further deletions can be managed approiatly.
public void Delete()
{
if (totalcourse < 1) {
Console.WriteLine ();
Console.WriteLine ("There is nothing to delete!");
Console.WriteLine ();
}else{
Console.WriteLine ();
Console.Write ("How many entries do you wish to remove?");
int removed = int.Parse (Console.ReadLine ());
for (int i = 0; i < removed; i++) {
Console.WriteLine ("Please type the index line number of the item you wish to remove.");
int delete = int.Parse (Console.ReadLine ());
school.RemoveAt (delete - 1);
totalcourse = totalcourse - 1;
Print ();
}
}
Console.WriteLine ();
}
//This method is called to create a new list of Courses to be created by the user.
public void New()
{
Console.WriteLine ();
if (howmany > 0) {
Clear ();
} else {
Console.Write ("How many courses do you want to create? ");
howmany = int.Parse (Console.ReadLine ());
Console.WriteLine ();
for (int i = 0; i < howmany; i++) {
Console.WriteLine ();
school.Add (new Course (prefix = Console.ReadLine (), courseName = Console.ReadLine (), courseNumber = Console.ReadLine (), courseHours = int.Parse (Console.ReadLine ()), descript = Console.ReadLine ()));
}
totalcourse = totalcourse + howmany;
Console.WriteLine ();
}
}
//If there is already a list in place this method will be called and you will be asked if you wish to delete and start new.
public void Clear()
{
Console.WriteLine ();
Console.Write ("You want to discard old work and start a new list? Enter True or False...:");
bool clean=bool.Parse(Console.ReadLine());
if (clean == true) {
school.Clear ();
totalcourse = 0;
howmany = 0;
New ();
} else
Console.WriteLine ("No changes will be made. Exiting to Main Menu...");
Console.WriteLine ();
}
/* public static void Myfour ()
{
Console.WriteLine ();
Console.WriteLine ("These are four pre loaded courses.");
Course c1 = new Course ("MISSILE", 84, 3, "The Course is for missiles", "CRN");
Console.WriteLine (c1);
Console.WriteLine ();
}*/
}
}
Your Course class needs to be static:
public class Course
and so does your choice method:
public static void Choice()
Static means you can use members (e.g. a method) of a class without having to create an instance of the class using 'new'. This is what you're trying to do, so the method and container class both need the static modifier. You'll need to make all the other methods in your 'Course' class static as well though.
Or, why don't you just create an instance of your Course class in your Main method:
Course myCourse = new Course();
myCourse.Menu();
myCourse.Choice();
Then your code will work
This should get you started. What I have done is
Made the constructor without arguments
Created instance of Course in main method and invoke its methods
This is by no means complete but should get you started.
using System;
using System.Collections.Generic;
namespace Lab4
{
public class MainClass
{
public static void Main (string[] args)
{
Console.WriteLine ("Welcome to the Course Monitoring System v1.0");
var c = new Course();
c.Menu();
c.Choice();
}
}
public class Course
{
private string courseNumber;
private string courseName;
private int courseHours;
private string descript;
private string prefix;
public List<Course> school = new List<Course> ();
private int howmany=0;
private int totalcourse=0;
//This section is for returning and adjusting values of private data through the main program.
public string cn{
get {return courseNumber; }
set {if (value != null)
cn = value;
}
}
public string name{
get{ return courseName; }
set{if (value!="")
name=courseName;
}
}
public int hours{
get {return courseHours; }
set {if (value != 0)
hours = value;
}
}
public string script {
get {return descript; }
set {
if (value != "")
script = value;
}
}
public string pfix {
get {return prefix; }
set {if (value != "")
pfix = value;
}
}
public Course()
{
}
public Course (string pfix, string name, string cn, int hours, string script)
{
courseNumber = cn;
courseName = name;
courseHours = hours;
descript= script;
prefix = pfix;
}
//This portion of code overrides the string and allows it to output the information held within the constructor.
public override string ToString ()
{
return prefix + " " + courseName+" " + courseNumber + " " + descript + " It is a " + courseHours + " hour course.";
}
//The menu application for my program
public void Menu()
{
Console.WriteLine ("Please choose from one of the following options: ");
Console.WriteLine ("......................................................................");
Console.WriteLine ("1.)Start a new Course List.");
Console.WriteLine ("2.)Delete Course from Current List.");
Console.WriteLine ("3.)Print Current Course List.");
Console.WriteLine ("4.)Add Course to Current List.");
Console.WriteLine ("5.)Shutdown Program");
}
//This is the controller for the menu. It allows for functionality to control the tasks requested by the user.
public void Choice()
{
int selection=int.Parse(Console.ReadLine());
while (selection >5 || selection < 1) {
Console.WriteLine ("Choice invalid. Please choose between 1 and 5.");
selection = int.Parse (Console.ReadLine ());
}
if (selection == 4) {
Add ();
Menu ();
Choice ();
Console.WriteLine ();
}
if (selection == 2) {
Delete ();
Menu ();
Choice ();
Console.WriteLine ();
}
if (selection == 3) {
Print ();
Menu ();
Choice ();
Console.WriteLine ();
}
if (selection == 1) {
New ();
Menu ();
Choice ();
Console.WriteLine ();
}
if (selection == 5) {
Console.WriteLine ();
Console.WriteLine ("Thank you for using this program for your scheduling needs.");
}
}
//This method when called will print a numbered list of courses refrenced by the created List
public void Print()
{
Console.WriteLine ();
Console.WriteLine ("Course Name.........Course Number.........Course Description........Course Hours");
Console.WriteLine ("********************************************************************************");
for (int i = 0; i < totalcourse; i++) {
int place = i + 1;
Console.WriteLine (place+".)"+school [i]);
}
Console.WriteLine ();
}
//This method will add an item to the end of the current list.
public void Add()
{
Console.WriteLine ();
Console.Write ("How many courses would you like to add at the end of your index?");
int numberAdded = int.Parse(Console.ReadLine ());
for (int i = 0; i < numberAdded; i++) {
Console.WriteLine ("Please use the following templet for your entries...");
Console.WriteLine ("Course Prefix, Course Name, Course Number, Course Hours, Course Description ");
school.Add (new Course (prefix = Console.ReadLine (), courseName = Console.ReadLine (),
courseNumber = Console.ReadLine (), courseHours = int.Parse (Console.ReadLine ()), descript = Console.ReadLine ()));
}
totalcourse = totalcourse + numberAdded;
Console.WriteLine ();
}
//This method will delete an Item from the list based on the position 0-x based on x-1, the output that is seen by the user. After each iteration it will
//also create a list so that further deletions can be managed approiatly.
public void Delete()
{
if (totalcourse < 1) {
Console.WriteLine ();
Console.WriteLine ("There is nothing to delete!");
Console.WriteLine ();
}else{
Console.WriteLine ();
Console.Write ("How many entries do you wish to remove?");
int removed = int.Parse (Console.ReadLine ());
for (int i = 0; i < removed; i++) {
Console.WriteLine ("Please type the index line number of the item you wish to remove.");
int delete = int.Parse (Console.ReadLine ());
school.RemoveAt (delete - 1);
totalcourse = totalcourse - 1;
Print ();
}
}
Console.WriteLine ();
}
//This method is called to create a new list of Courses to be created by the user.
public void New()
{
Console.WriteLine ();
if (howmany > 0) {
Clear ();
} else {
Console.Write ("How many courses do you want to create? ");
howmany = int.Parse (Console.ReadLine ());
Console.WriteLine ();
for (int i = 0; i < howmany; i++) {
Console.WriteLine ();
school.Add (new Course (prefix = Console.ReadLine (), courseName = Console.ReadLine (), courseNumber = Console.ReadLine (), courseHours = int.Parse (Console.ReadLine ()), descript = Console.ReadLine ()));
}
totalcourse = totalcourse + howmany;
Console.WriteLine ();
}
}
//If there is already a list in place this method will be called and you will be asked if you wish to delete and start new.
public void Clear()
{
Console.WriteLine ();
Console.Write ("You want to discard old work and start a new list? Enter True or False...:");
bool clean=bool.Parse(Console.ReadLine());
if (clean == true) {
school.Clear ();
totalcourse = 0;
howmany = 0;
New ();
} else
Console.WriteLine ("No changes will be made. Exiting to Main Menu...");
Console.WriteLine ();
}
/* public static void Myfour ()
{
Console.WriteLine ();
Console.WriteLine ("These are four pre loaded courses.");
Course c1 = new Course ("MISSILE", 84, 3, "The Course is for missiles", "CRN");
Console.WriteLine (c1);
Console.WriteLine ();
}*/
}
}
The first problem with your class is that the Course class contains a List<Course> school variable. A School is another logical entity and should be in another class. I think the Course class should be a class on it's own, without any static members. All the Console related functions and the school variable should be enclosed in a (maybe static, if that's a requirement) School class.
Your main function would then call
School.Menu();
School.Choice();
The way you called Course.Choice() which is a className.methoddName() is meant for accessing a static method. That means you will need to change your
public void Choice() { }
public void Menu() { }
to
public static void Choice() { }
public static void Menu() { }
However, like I said before, since Choice() and Menu() are now static, therefore everything that is called within these methods have to be static as well, such as Add(), Delete(), Print().
So what does it mean to be a static method? - You don't (and can't) instantiate them to access them. The other approach to this, is to simply create an instance of class Course using the new keyword:
Course cr = new Course();
//This works because Course and MainClass are under the same namespace
//Or else, you will need to do this:
OtherNamespace.Class x = new OtherNamespace.Class() ;
and now you can access all the non-static methods in Course class! Like this:
cr.Menu();
cr.Choice();
Create an instance would seem to be an easier approach to solve your problem, because all of your methods are instance. But you should really understand when is more appropriate to use which. You can read more about that here.
Even though you only asked about calling non-static. I really think you have a lot of improvement to do on Course class. You clump too many things inside the class. For example, you can create a new class just to store all the properties like cn, name, hours, etc. Here it will be a good idea to set them as static property, then you can simply access them anywhere using TheNewClass.hours.

Field 'xxx' is never assigned to, and will always have its default value null

My error:
Field 'StockManagement.LargeItems1.largeS' is never assigned to, and will always have its default value null
My code:
namespace StockManagement
{
class LargeItems1
{
private Stack<string> largeS;
public LargeItems1()
{
Stack<string> largeS = new Stack<string>();
}
public void LargeItemsAdd()
{
string usersInput2, tempValue;
int tempValueI = 0;
bool attempt = false;//, whichOne = false;
Console.WriteLine("Would you like to remove or add an item to the storage area \n Reply add OR remove");
string usersInput = Console.ReadLine();
usersInput = usersInput.ToLower();
if (usersInput.Contains("remove"))
{
LargeItemsRemove(largeS);
return;
}
else if (usersInput.Contains("add"))
{
Console.WriteLine("Please input (numerically) how many IDs you'd like to add");
tempValue = Console.ReadLine();
attempt = int.TryParse(tempValue, out tempValueI);
while (!attempt)
{
Console.WriteLine("Please input (numerically) how many IDs you'd like to add, you did not input a numeric value last time");
tempValue = Console.ReadLine();
attempt = int.TryParse(tempValue, out tempValueI);
}
for (int i = 0; i < tempValueI; i++)
{
Console.WriteLine("Please input the ID's (one at a time) of the item you would like to add");
usersInput2 = Console.ReadLine();
if (largeS.Contains(usersInput2))
{
Console.WriteLine("That ID has already been stored");
}
else
{
largeS.Push(usersInput2);
}
}
foreach (var item in largeS)
{
Console.WriteLine("Current (large) item ID's: " + item);
}
}
}
public void LargeItemsRemove(Stack<string> largeS)
{
if (largeS.Contains(null))
{
Console.WriteLine("No IDs stored");
}
else
{
string popped = largeS.Pop();
foreach (var item in largeS)
{
Console.WriteLine("Pop: " + item);
}
Console.WriteLine("Removed ID = " + popped);
}
}
}
}
I don't understand how to assign my values to the instances. I'd appreciate any help that can be provided!
Change your constructor to initialize the field instead of the local variable:
public LargeItems1()
{
this.largeS = new Stack<string>();
}
You have to initialize your field largeS, using the this keyword, in this way:
this.largeS = new Stack<string>();
The this keyword is used to refer to the current instance of the class. If you use instead:
Stack<string> largeS = new Stack<string>();
you're just initializing a new local variable that has nothing to do with your private field.
Check the MSDN documentation about this keyword.

How to know whether there is a round has been caused by parents (A=>B=>C=>A)

I have the following structure:
[Employee]
ID
Manager1ID
Manager2ID
Scenario:
I want to make a validation to ensure that the chosen Manager1 or Manager2 does not cause a round. In other words, I want to know whether this case exists:
The manager of A is B & the manager of B is C and the manger of C is also A // not valid
A => B => C => A
To tell the user that A is not a valid manager for C because C is already a manager of A
.
The problem:
I though of checking in a while loop the managers as parents in a tree, and when I found the chosen manager in the list I know that it is not valid. (Two loops for tow lists for Manager1 and Manager2)
The problem is that every employee might have two managers and a round maybe exists in a case like this:
A => B (Manager1) => C (Manager2) => A
Which is not able to check in my suggested solution.
Any idea!
You try to find a cycle in a directed graph.
starting from the employee in question, do a breadth first search on the set of managers and keep accumulating the list of managers you come across in a list. Each time you add an entry to the list, check if it would create a duplication. If it would, it means you have reached the condition you wanted to check for. Keep continuing this process until you either hit a duplication condition or you reach a node which does not have managers
Use a recursive function:
List<Employee> lineage = new List<Employee>();
Validate(theUser, lineage);
public void Validate(Employee employee, List<Employee> lineage)
{
if (lineage.Contains(employee))
throw new InvalidOperationException("Circular graph");
lineage.Add(employee);
if (employee.Manager != null)
Validate(employee.Manager, lineage)
}
I have provided a complete generic solution for n number of reportees which is more logical than reportees. If you like to rename reportees to managers, you can do so.
You can modify the traversal to suit your needs. I have tested this with cycle and without cycle. It seems to work fine. Let me know if this works for you.
using System;
using System.Collections.Generic;
namespace GenericDictionary
{
class Program
{
static void Main(string[] args)
{
Employee employee = new Employee("Employee", null);
Employee manager = new Employee("Manager", employee);
Employee CEO = new Employee("CEO", manager);
CEO.AddReportee(new Employee("Manager2", employee));
// Uncomment this line to see exception in action
// employee.AddReportee(CEO);
try
{
CEO.DisplayReportees();
}
catch (InvalidOperationException ex)
{
Console.WriteLine();
Console.WriteLine("***** Exception: " + ex.Message + " *****");
}
Console.ReadLine();
}
public class Employee
{
public List<Employee> Reportees { get; private set; }
public string Name { get; private set; }
public Employee(string name, Employee reportee)
{
this.Reportees = new List<Employee>();
this.Name = name;
this.Reportees.Add(reportee);
}
public void AddReportee(Employee reportee)
{
Reportees.Add(reportee);
}
int indentationCount = 0;
List<Employee> traversedNodes = new List<Employee>();
void DisplayReportees(Employee employee)
{
traversedNodes.Add(employee);
for (int i = 0; i < indentationCount; i++)
Console.Write(" ");
Console.WriteLine(employee.Name);
indentationCount = indentationCount + 3;
foreach (Employee reportee in employee.Reportees)
{
if (AlreadyTraversed(reportee))
throw new InvalidOperationException("Circular graph at node " + reportee.Name);
if (reportee != null)
DisplayReportees(reportee);
}
indentationCount = indentationCount - 3;
traversedNodes.Remove(employee);
}
bool AlreadyTraversed(Employee employee)
{
return traversedNodes.Contains(employee);
}
public void DisplayReportees()
{
DisplayReportees(this);
}
}
}
}
Use the following recursive function:
Boolean CheckManagers(Employee emp)
{
if ((emp.Manager1ID.HasValue && emp.Manager1ID == emp.ID) ||
(emp.Manager2ID.HasValue && emp.Manager2ID == emp.ID)) return false;
return
(
(!emp.Manager1ID.HasValue || (emp.Manager1ID.HasValue && CheckManagers((Employee) emp.Manager1)) &&
(!emp.Manager2ID.HasValue || (emp.Manager2ID.HasValue && CheckManagers((Employee) emp.Manager2))
);
}

Categories

Resources