I am entering code into a list. However, when I try to iterate through the code in a method call, nothing is being returned.
The problem code is found in "public class iterating". I am not sure why it won't execute.
Basically, I would like someone to enter information. Once the information has been entered, I would then like the user to iterate through the list via a method call.
using System;
using System.Text.RegularExpressions;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
public class Iterating
{
List<String> employees = new List<String>();
public void Test2()
{
//This is where I am trying to iterate//
for (int i = 0; i < employees.Count; i++)
{
Console.WriteLine(employees[i]);
}
}
}
public class Testing
{
public void Test1()
{
while (true)
{
List<String> employees = new List<String>();
Regex regex = new Regex(#"((.{5})-\d{2,5}-\d{2,5})|(#.*.com)");
Console.WriteLine("Please enter an e-mail");
string input = Console.ReadLine();
if(string.Equals(input, "quit", StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine("You have quit the program");
break;
}
else if (match.Success)
{
Console.WriteLine(match.Value);
employees.Add(match.Value);
}
}
}
}
public class Program
{
public static void Main()
{
Testing T1 = new Testing();
T1.Test1();
Iterating I1 = new Iterating();
I1.Test2();
}
}
You don't get any output since
Every loop in the collection stage uses a new employees list.
Your two classes do not share the same employees list - they each have their own separate list.
If you want the iterating class to print the contents of a list, you need to pass it the list in question.
A partial example:
public class Program {
public static void Main() {
List<String> employees = new List<String>();
Testing T1 = new Testing();
T1.Test1(employees);
Iterating I1 = new Iterating();
I1.Test2(employees);
}
}
You would modify your test methods to use the passed list rather than create new ones
public class Iterating {
List<String> employees = new List<String>();
public void Test2()
{
//This is where I am trying to iterate//
for (int i = 0; i < employees.Count; i++)
{
Console.WriteLine(employees[i]);
}
}
}
employees is always empty since this doesn't have anything to do with Testing.employees you might want to remove it and pass the list into Test2 or into the constructor.
Also, Testing.employees should be outside the while look
You can redesign your class like this
public class Iterating
{
public void Test2(List<String> employees)
{
//This is where I am trying to iterate//
for (int i = 0; i < employees.Count; i++)
{
Console.WriteLine(employees[i]);
}
}
}
public class Testing
{
public List<String> Test1()
{
List<String> employees = new List<String>();//this should be outside the while loop
while (true)
{
Regex regex = new Regex(#"((.{5})-\d{2,5}-\d{2,5})|(#.*.com)");
Console.WriteLine("Please enter an e-mail");
string input = Console.ReadLine();
if(string.Equals(input, "quit", StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine("You have quit the program");
break;
}
else if (match.Success)
{
Console.WriteLine(match.Value);//where is the match var
employees.Add(match.Value);//where is the match var
}
}
return employees;
}
}
public class Program
{
public static void Main()
{
Testing T1 = new Testing();
var employees = T1.Test1();
Iterating I1 = new Iterating();
I1.Test2(employees);
}
}
Related
using System;
using System.Collections.Generic;
using System.IO;
namespace _2._1
{
class Narys
{
public string Vardas { get; set; }
public string Pavarde { get; set; }
public double Pinigai { get; set; }
public Narys()
{
}
public Narys(string vardas, string pavarde, double pinigai)
{
Vardas = vardas;
Pavarde = pavarde;
Pinigai = pinigai;
}
List<Narys> DuomenuSkaitymas()
{
List<Narys> nariai = new List<Narys>();
string[] eilutes = File.ReadAllLines(#"nariai.txt");
foreach (string eilute in eilutes)
{
string[] duomenys = eilute.Split(' ');
string vardas = duomenys[0];
string pavarde = duomenys[1];
double pinigai = double.Parse(duomenys[2]);
Narys narys = new Narys(vardas, pavarde, pinigai);
nariai.Add(narys);
}
return nariai;
}
void DuomenuIrasymas(List<Narys> nariai)
{
string[] eilutes = new string[nariai.Count];
for (int i = 0; i < nariai.Count; i++)
{
eilutes[i] = String.Format("{0} {1} {2}", nariai[i].Vardas, nariai[i].Pavarde, nariai[i].Pinigai);
}
File.WriteAllLines(#"nariaiAts.txt", eilutes);
}
void DuomenuParodymas(List<Narys> nariai)
{
foreach (Narys narys in nariai)
{
Console.WriteLine("Vardas: {0}\nPavarde: {1}\nPinigai: {2}", narys.Vardas, narys.Pavarde, narys.Pinigai);
}
}
}
class Program
{
static void Main(string[] args)
{
Program p = new Program();
List<Narys> nariai = p.DuomenuSkaitymas();
p.DuomenuIrasymas(nariai);
}
}
}
And why i'm getting those errors ?
I think it should work, but it isn't, so i guess you will be able to solve this sh*t. Also, i'm studying in university and i am doing this by example and it really should work. I think there should be enough info for you guys.
Just look at your code:
class Program
{
static void Main(string[] args)
{
Program p = new Program();
List<Narys> nariai = p.DuomenuSkaitymas();
p.DuomenuIrasymas(nariai);
}
}
You are declaring the class Program that contains only a static method. Then you instantiate that class in variable p. Then you are trying to access some DuomenuSkaitymas method of it. But it contains only a static method. So how should this work?
You probably wanted to instantiate class Narys in p instead of Program.
Just a pro tip: never use identifier names in your local language, even if it looks more understandable at first. Your code might well end in the hands of others who don't understand your language. Believe me, you will choose better identifiers if you want others to understand your code - and that will be valuable to you too.
Your class Program just contains the main() method, so the IDE informs you that Program does not contains DuomenuSkaitymas method.
That method (DuomenuSkaitymas) , is defined in the Nary's class, so probably you need to modify you main method to
class Program
{
static void Main(string[] args)
{
Narys p = new Narys();
List<Narys> nariai = p.DuomenuSkaitymas();
p.DuomenuIrasymas(nariai);
}
}
I didn't check what the program means itself just clarifying your CS1061, so if there is other problems try to look closely to the code and understand what it means. If any other issue non related to this CS1061 arises after that you could try to post a new question with your issues or ideas about it.
I've written a small program where I need to insert some objects (employees in my case) in my MongoDB database. Each employee needs to get a random name from a predefined list with strings.
This is what I came up with and is working:
class Program
{
public class Employee
{
public string Name { get; set; }
}
static void Main(string[] args)
{
MongoClient client = new MongoClient();
var server = client.GetServer();
var db = server.GetDatabase("testdb");
var collection = db.GetCollection<Employee>("testcollection");
Random random = new Random();
List<string> names = new List<string>() {"John","Matthew","Chris"};
for (int i = 0; i < 5; i++)
{
int nameIndex = random.Next(0, 3);
string nameValue = names[nameIndex];
Employee employee = new Employee
{
Name = nameValue
};
collection.Save(employee);
}
}
}
However, this code feels like a bit dirty and I am lookingfor a nice way to clean this up. Especially if I want to add more properties to my employee object.
Edit: #Eric Lippert
Of course! To start with, practically everything happens in the main method. With a single list it's fine, but I'd like to add more data to my employee object. It won't be tiny in the future.
So, if I want to add a few more List's, I have to duplicate my current code. For example, I'd like to iterate over another list with job types (10 items) and another one for locations (50 items). For each property I want to add to my Employee-object, I have to write a new line of the Next()-function from my Random object.
Edit 3:
public static IMongoDatabase Connect()
{
MongoClient client = new MongoClient();
var db = client.GetDatabase("testdb");
return db;
}
static void Main(string[] args)
{
Connect();
var collection = db.GetCollection<Employee>("testcollection");
}
Error: The name 'db' doesnt exist in the current context.
If you want to apply more random values from other lists you can do the following, which basically comes down to removing the unnecessary nameIndex and nameValue variables:
for (int i = 0; i < 5; i++)
{
Employee employee = new Employee
{
Name = names[random.Next(0, names.Count)]
};
collection.Save(employee);
}
You could abstract the separate parts in to new classes say a DatabaseSeeder and Database, this just cleans up the responsibilities instead of having it all in the main method
class Program
{
public class Employee
{
public string Name { get; set; }
}
public class Database
{
public ICollection<Employee> GetCollection()
{
MongoClient client = new MongoClient();
var server = client.GetServer();
var db = server.GetDatabase("testdb");
var collection = db.GetCollection<Employee>("testcollection");
}
}
public class DatabaseSeeder
{
private ICollection<Employee> collection;
public DatabaseSeeder(ICollection<Employee> collection)
{
this.collection = collection;
}
public void Seed()
{
Random random = new Random();
List<string> names = new List<string>() {"John","Matthew","Chris"};
for (int i = 0; i < 5; i++)
{
int nameIndex = random.Next(0, 3);
string nameValue = names[nameIndex];
Employee employee = new Employee
{
Name = nameValue
};
collection.Save(employee);
}
}
}
static void Main(string[] args)
{
var collection = new Database().GetCollection();
var databaseSeeder = new DatabaseSeeder(collection);
databaseSeeder.Seed();
}
}
I have an enum with 30 items in it. Each item has a corresponding function with the same name. I would like to be able to call the function by referencing the enum at a certain position.
So if the value at enum[0] = Foo, I would like to be able to call Foo(string bar) by using something like enum(0)("foobar")
In the end the point is I am running each function as a task like so:
enum Test { AA, BB, CC, DD ....}
tasks[0] = Task.Run(() => { prices[0] = AA("a string"); });
tasks[1] = Task.Run(() => { prices[1] = BB("a string"); });
tasks[2] = Task.Run(() => { prices[2] = CC("a string"); });
//for 30 tasks
What I would like to do is something along the lines of:
enum Test { AA, BB, CC, DD ....}
for (int i = 0; i < 30; i++)
{
tasks[i] = Task.Run(() => { prices[i] = (Test)i("a string"); });
}
Task.WaitAll(tasks.ToArray());
Is this something that is even possible?
EDIT:
The enum relates to controls on a form so i have an array of textboxs, label and a array of prices that is populated with the results of the functions:
enum Dealers { Dealer1, Dealer2 ... Dealer29, Dealer30 };
static int noOfDealers = Enum.GetNames(typeof(Dealers)).Length;
decimal[] prices = new decimal[noOfDealers];
TextBox[] textBox = new TextBox[noOfDealers];
Label[] boxes = new Label[noOfDealers];
for (int i = 0; i < noOfDealers; i++)
{
textBox[i] = Controls.Find("txt" + (Dealers)i, true)[0] as TextBox;
boxes[i] = Controls.Find("box" + (Dealers)i, true)[0] as Label;
prices[i] = 0;
}
//RUN 30 TASKS TO POPULATE THE PRICES ARRAY
for (int i = 0; i < noOfDealers; i++)
{
textBox[i].Text = "£" + prices[i].ToString();
}
//LOOP THROUGH PRICES ARRAY AND FIND CHEAPEST PRICE, THEN COLOUR THE LABEL BACKGROUND GREEN FOR THE TEXT BOX WITH THE NAME AT ENUM VALUE WHATEVER I IS
I guess i am just trying to make my code as concise as possible, there is the potential for the amount of tasks to double and didn't want to end up with 60 lines to populate the tasks array
I would create dictionary and map enum to actions:
Dictionary<Test, Func<string,double>> actions = new Dictionary<Test, Func<string,double>>()
{
{Test.AA, (x) => { return 5;}},
{Test.BB, (x) => { return 15; }},
}; //x is your string
var res = actions[Test.AA]("hello");
I would strongly suggest using a built in construct - like an extension method and a simple switch:
public static int GetPriceWithString(this Test test, string str)
{
switch (test)
{
case Test.AA:
break;
case Test.BB:
break;
case Test.CC:
break;
case Test.DD:
break;
default:
throw new ArgumentOutOfRangeException(nameof(test), test, null);
}
}
then your loop looks almost the same:
for (int i = 0; i < 30; i++)
{
tasks[i] = Task.Run(() =>
{
prices[i] = ((Test)i).GetPriceWithString("a string");
});
}
What you want to do is possible with reflection, which can be a powerful tool - but ideally should only be used as a last resort, as it will hide what could be compile time errors, and cause less code readability.
Using a simple switch like this makes your code self-documented, so when you come back to this in a month you can quickly remember what the intention was.
How about using an array of delegates:
using System;
using System.Threading.Tasks;
namespace ConsoleApplication
{
class Program
{
private static int AA(string a) { return 0; }
private static int BB(string a) { return 1; }
private static int CC(string a) { return 2; }
private static Func<string, int>[] functions = new Func<string, int>[] { AA, BB, CC };
private static int[] prices = new int[functions.Length];
private static Task[] tasks = new Task[functions.Length];
static void Main(string[] args)
{
for (int i = 0; i < functions.Length; ++i)
tasks[i] = Task.Run(() => { prices[i] = functions[i]("a string"); });
Task.WaitAll(tasks);
}
}
}
An eg. speaks a lot more than words.
I used it in a winform so the this refers to win form.
I have assumed all your methods are public , have same signature & return the same type.
enum MyName { AA,BB,CC};
//Call this in one of your methods
string [] strVal= Enum.GetNames(typeof(MyName));
int x = CallFunction(strVal[0], "A");
int y = CallFunction(strVal[1], "h");
int z = CallFunction(strVal[1], "C");
//End Call this in one of your methods
int CallFunction(string strName,string strValue)
{
return Convert.ToInt32(this.GetType().InvokeMember(strName, BindingFlags.Public | BindingFlags.InvokeMethod|BindingFlags.Instance, null, this, new object[] { strValue }));
}
public int AA(string s)
{
return 1;
}
public int BB(string s)
{
return 2;
}
public int CC(string s)
{
return 3;
}
Another solution. I hope somebody will consider it as overkill :)
Create abstract class DealerBase.
public abstract class DealerBase
{
public string Name { get; }
public decimal Price { get; set; }
protected DealerBase(string name)
{
Name = name;
}
public abstract void UpdatePrice();
}
Then create classes for every dealers you have and implement own logic for UpdatePrice method.
public class Dealer1 : DealerBase
{
public Dealer1() : base("DealerOne") { }
public override void UpdatePrice()
{
//Calculate price
Price = DealerOneCalculationMethod();
}
}
public class Dealer2 : DealerBase
{
public Dealer2() : base("DealerTwo") { }
public override void UpdatePrice()
{
//Calculate price
Price = DealerTwoCalculationMethod();
}
}
And so on..
Then you just create collection of dealers which can be easily iterated
var dealers = new List<DealerBase>
{
new Dealer1(),
new Dealer2()
}
foreach(var dealer in dealers)
{
dealer.UpdatePrice();
}
You can loop dealers and generate textboxes, labels in the winforms.
But I suggest to use DataGridView where code will be tiny clearer.
First implement INotifyPropertyChanged interface in the base class DealerBase
public abstract class DealerBase : INotifyPropertyChanged
{
public string Name { get; }
protected decimal _Price;
public decimal Price
{
get { return _Price; }
set
{
if (Equals(_Price, value)) return;
_Price = value;
// next method will inform DataGridView about changes
// and update value there too
RaisePropertyChanged();
}
protected DealerBase(string name)
{
Name = name;
}
public abstract void UpdatePrice();
// Implementation of INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
The in the Form you can create BindingList<DealerViewModelBase> and set it to DataGridView.DataSource
public class YourForm: Form
{
public YourForm()
{
InitializeComponent();
var dealers = new List<DealerBase>
{
new Dealer1(),
new Dealer2()
};
var bindSource = new BindingList<DealerBase>(dealers);
dataGridView.DataSource = bindSource;
}
// Add button which update prices for all dealers
private void ButtonUpdatePrices_Click(object sender, EventArgs e)
{
var dealers = (BindingList<DealerBase>)dataGridView.DataSource;
foreach (var dealer in dealers)
{
dealer.UpdatePrice();
// Because we call `RaisePropertyChanged` in
// setter of Price - prices will be automatically
// updated in DataGridView
}
}
}
Idea of this approach you put different logic of different dealers in the separated class which. Because all dealer classes will inherit from same abstract class you can add different dealers to the collection.
You already have hardcoded enums and correspondent method which you try to link together. This approach make using of dealers collection little bid easy
with my code, I'm supposed to be able to call a question from my file at random and not reuse that question again.
But for some reason I'm stuck in the while loop and after a few hours of searching I still can't see why, so I hope you guys can help me out.
(he gets stuck after he generated 8 questions)
Code (for the generatequestion one, if you need more I can paste it but I hope this gives enough information):
lineCount = File.ReadLines(pad).Count();
questions = new string[lineCount, 2];
public string GenerateQuestion(int total)
{
if (total <= 10)
{
Random ran = new Random();
questionNumber = ran.Next(lineCount);
while (previousQuestions.Contains(questionNumber))
{
questionNumber = ran.Next(lineCount);
}
}
previousQuestions[questionCount] = questionNumber;
questionCount++;
return questions[questionNumber, 0];
}
You could make a method to return the lines in the file in random order.
public string[] GetQuestionsInRandomOrder()
{
var lines = File.ReadAllLines("test.txt");
var rnd = new Random();
lines = lines.OrderBy(line => rnd.Next()).ToArray();
return lines;
}
Then as you use the questions you can remove them from the array.
var isRemoved = Array.remove(array, item);
https://msdn.microsoft.com/en-us/library/vstudio/bb397721%28v=vs.100%29.aspx
This is easier that what I had before and will give greater control. I would create a class for this and this example is a starting point. You can add more functionality as you go along. By having a class to do all this work you can add methods to do additional features later on without having to rewrite code.
public class Logic
{
public List<string> AllQuestionsInRandomOrder { get; set; }
public List<string> QuestionsThatHaveBeenRemoved { get; set; }
public Logic()
{
QuestionsThatHaveBeenRemoved = new List<string>();
AllQuestionsInRandomOrder = GetQuestionsInRandomOrder().ToList();
}
public string GetUnusedQuestion()
{
var question =
AllQuestionsInRandomOrder.FirstOrDefault(x => !QuestionsThatHaveBeenRemoved.Contains(x));
QuestionsThatHaveBeenRemoved.Add(question);
return question;
}
public IEnumerable<string> GetQuestionsInRandomOrder()
{
var lines = File.ReadAllLines("test.txt").ToList();
var rnd = new Random();
lines = lines.OrderBy(line => rnd.Next()).ToList();
return lines;
}
public void RemoveQuestion(List<string> questions, string questionToRemove)
{
questions.Remove(questionToRemove);
}
}
I would avoid using loops and break the problem into separate methods or functions. It will make it easier to debug. This implementation does not separate the questions and answers out, so you will need to add a method that returns a dictionary of the questions and answers.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main()
{
var questions = new Questions();
var firstQuestion = questions.GetUnusedQuestion();
Console.WriteLine(firstQuestion);
}
}
class Questions
{
public string FileName { get; set; }
public static List<string> AllQuestionsAndAnswersFromFile { get; set; }
public List<string> AllQuestionsInRandomOrder { get; set; }
public List<string> QuestionsThatHaveBeenRemoved { get; set; }
public Questions()
{
FileName = "text.txt";
QuestionsThatHaveBeenRemoved = new List<string>();
AllQuestionsAndAnswersFromFile = new List<string>();
ReadQuestionsFromFile();
AllQuestionsInRandomOrder = GetQuestionsInRandomOrder().ToList();
}
public string GetUnusedQuestion()
{
var question =
AllQuestionsInRandomOrder.FirstOrDefault(x => QuestionsThatHaveBeenRemoved.Contains(x));
QuestionsThatHaveBeenRemoved.Add(question);
return question;
}
private static IEnumerable<string> GetQuestionsInRandomOrder()
{
var lines = AllQuestionsAndAnswersFromFile;
var rnd = new Random();
lines = lines.OrderBy(line => rnd.Next()).ToList();
return lines;
}
public void RemoveQuestion(List<string> questions, string questionToRemove)
{
questions.Remove(questionToRemove);
}
public void ReadQuestionsFromFile()
{
using (var reader = new StreamReader(FileName, Encoding.Default))
{
var text = reader.ReadToEnd();
var lines = text.Split('=');
foreach (var s in lines)
{
AllQuestionsAndAnswersFromFile.Add(s);
}
}
}
}
}
When you run out of questions, let's see what
while (previousQuestions.Contains(questionNumber))
{
questionNumber = ran.Next(lineCount);
}
actually does:
Is questionNumber one of the questions we already asked?
Yes, get a new question number. (because we've asked all the questions)
Is questionNumber one of the questions we already asked?
yes, get a new question number. (because we've asked all the questions)
A solution in this case would be to shuffle your questions that you return, removing them as you grab them.
I think what i have to do is split and pull data to do the following:
I have created a class, with the following array and method getContactList. I need to create a method getFirstNames() and return all the first names from the address book into the variable firstNames in a Test class and display them on the console.
class ContactList
{
public String[] contactList =
{
"John, Smith, jsmith#nbcc.ca, (506) 555-1234",
"Frank, Sinatra, fsinatra#nbcc.ca, (506) 696-1234",
"Joan, Rivers, jrivers#nbcc.ca, (506) 696-5678",
"Freddy, Mercury, fmercury#nbcc.ca, (506) 653-1234",
"Freddy, Kruger, fkruger#nbcc.ca, (506) 658-1234"
};
public String[] getContactList()
{
return contactList;
}
public String getLastNames()
{
string lastnames = "";
return lastnames;
}
}
class Program
{
static void Main(string[] args)
{
ContactList firstNames = new ContactList();
Console.WriteLine(firstNames.getFirstNames());
Console.WriteLine();
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
Yours isn't exactly the best approach, but to achieve what you want...
(assuming you want to separate the names by , )
public string getFirstNames(){
StringBuilder sb=new StringBuilder();
foreach(var x in contactList){
var tmp=x.Split(',');
sb.Append(tmp[0]);
sb.Append(",");
}
return sb.ToString();
}
Better design it this way:
class ContactList
{
string firstName, lastName, eMail, ContactNo;
//Properties (getters/setters for above attributes/fields
}
class ContactListHandler
{
public List<string> GetFirstNames(string[] contactsText)
{
List<string> stringList = new List<string>();
foreach (string s in contactsText)
{
var x = contactsText.split(',');
stringList.Add(x[0]);
}
return stringList;
}
//and other functions
}
Main()
{
ContactListHandler cHandler = new ContactListHandler();
List<string> contactsString = cHandler.GetFirstNames(//your string variable containing the contacts);
foreach(string s in contactsString)
{
Console.WriteLine(s);
}
}
Yes it has increased code but only for once, now you can use it in an Object-oriented way for any string,etc.
It's working I checked :) good luck with your development
using System.IO;
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main()
{
// Just to hold data
string[] data = new String[]{"John, Smith, jsmith#nbcc.ca, (506) 555-1234","Frank, Sinatra, fsinatra#nbcc.ca, (506) 696-1234","Joan, Rivers, jrivers#nbcc.ca, (506) 696-5678","Freddy, Mercury, fmercury#nbcc.ca, (506) 653-1234","Freddy, Kruger, fkruger#nbcc.ca, (506) 658-1234"};
// Create new contact list object
ContactList contacts = new ContactList(data);
// Call our method
contacts.PrintLastNames();
}
}
public class ContactList
{
// Declare properties
// google C# getter setter
private List<string> cList;
public List<string> CList{
get{ return cList; }
}
// Constructor
public ContactList(string[] _contactList)
{
// When creating new instance, take array of contacts and put into list
this.cList = _contactList.ToList();
}
// This will print out the names
public void PrintLastNames()
{
// Google lambda expression C# for more info on iteration
// With each string in cList, split by comas and use the first element
this.cList.ForEach( x => Console.WriteLine(x.Split(',')[0]));
// Use this for last names
//this.cList.ForEach( x => Console.WriteLine(x.Split(',')[1]));
}
// This will return names in list
public List<string> GetLastNames()
{
// Google List Collection Generic C# for more info
List<string> namesList = new List<string>();
this.cList.ForEach( x => namesList.Add( x.Split(',')[0] ));
return namesList;
}
}