IEnumerable - Move Next

I have an IEnumerable from which I need to get each element and display it one by one. Mapping is not a continuous process. Ie I have to select one element and display it in the user interface, and then wait for some user feedback on this element, and then go to the next element. For example, from the code below, I need to get a question, then display it to the user, then click "Sign in", and then proceed to select the next question.

My question is: how do I do this? Is IEnumerable the best way to achieve this, or do I need to go back to the list and start storing indexes and incrementing it one at a time?

Please note that I am using .NET 3.5.

the code:

class Program { static void Main(string[] args) { Exam exam1 = new Exam() { Questions = new List<Question> { new Question("question1"), new Question("question2"), new Question("question3") } }; var wizardStepService = new WizardStepService(exam1); var question = wizardStepService.GetNextQuestion(); //Should output question1 Console.WriteLine(question.Content); Console.ReadLine(); //Should output question2 but outputs question1 question = wizardStepService.GetNextQuestion(); Console.WriteLine(question.Content); Console.ReadLine(); //Should output question3 but outputs question1 question = wizardStepService.GetNextQuestion(); Console.WriteLine(question.Content); Console.ReadLine(); } } public class Question { private readonly string _text; public Question(string text) { _text = text; } public string Content { get { return _text; } } } internal class Exam { public IEnumerable<Question> Questions { get; set; } } internal class WizardStepService { private readonly Exam _exam; public WizardStepService(Exam exam) { _exam = exam; } public Question GetNextQuestion() { foreach (var question in _exam.Questions) { //This always returns the first item.How do I navigate to next //item when GetNextQuestion is called the second time? return question; } //should have a return type hence this or else not required. return null; } } 
+4
source share
3 answers

Yes, GetEnumerator() should work fine; although, strictly speaking, you need to handle Dispose() :

 internal class WizardStepService : IDisposable { private IEnumerator<Question> _questions; public WizardStepService(Exam exam) { _questions = exam.Questions.GetEnumerator(); } public void Dispose() { if (_questions != null) _questions.Dispose(); } public Question GetNextQuestion() { if (_questions != null) { if (_questions.MoveNext()) { return _questions.Current; } Dispose(); // no more questions! } //should have a return type hence this or else not required. return null; } } 

as well as:

 using (var wizardStepService = new WizardStepService(exam1)) { var question = wizardStepService.GetNextQuestion(); //Should output question1 Console.WriteLine(question.Content); Console.ReadLine(); //Should output question2 but outputs question1 question = wizardStepService.GetNextQuestion(); Console.WriteLine(question.Content); Console.ReadLine(); //Should output question3 but outputs question1 question = wizardStepService.GetNextQuestion(); Console.WriteLine(question.Content); Console.ReadLine(); } 

However, since you are not actually checking the result each time, you can also do something like:

 using (var questions = exam1.Questions.GetEnumerator()) { questions.MoveNext(); var question = questions.Current; //Should output question1 Console.WriteLine(question.Content); Console.ReadLine(); //Should output question2 but outputs question1 questions.MoveNext(); question = questions.Current; Console.WriteLine(question.Content); Console.ReadLine(); //Should output question3 but outputs question1 questions.MoveNext(); question = questions.Current; Console.WriteLine(question.Content); Console.ReadLine(); } 

Or as a final thought, maybe just:

 var questions = exam1.Questions.Take(3).ToArray(); //Should output question1 Console.WriteLine(questions[0].Content); Console.ReadLine(); //Should output question2 but outputs question1 Console.WriteLine(questions[1].Content); Console.ReadLine(); //Should output question3 but outputs question1 Console.WriteLine(questions[2].Content); Console.ReadLine(); 
+4
source

Well, you can save the IEnumerator<T> instead and change GetNextQuestion to:

 return _exam.MoveNext() ? _exam.Current : null; 

However, at this point you are not actually adding values ​​with the Exam or WizardStepService , and you can simply use IEnumerator<T> directly in Main . Note that your Main method itself is a little strange - it repeated the code where the foreach would be simpler - and you unconditionally ask three questions.

Note: if you have a type with IEnumerator<T> as the field, you probably want to implement IDisposable to get rid of the iterator, too - everything gets a little dirty.

+2
source

Try the following:

 class Program2 { static void Main(string[] args) { Exam exam1 = new Exam() { Questions = new List<Question> { new Question("question1"), new Question("question2"), new Question("question3") } }; var wizardStepService = new WizardStepService(exam1); foreach (var question in wizardStepService.GetQuestions()) { Console.WriteLine(question.Content); Console.ReadLine(); } } } public class Question { private readonly string _text; public Question(string text) { _text = text; } public string Content { get { return _text; } } } internal class Exam { public IEnumerable<Question> Questions { get; set; } } internal class WizardStepService { private readonly Exam _exam; public WizardStepService(Exam exam) { _exam = exam; } public IEnumerable<Question> GetQuestions() { foreach (var question in _exam.Questions) { //This always returns the first item.How do I navigate to next //item when GetNextQuestion is called the second time? yield return question; } //should have a return type hence this or else not required. //return null; } } 
0
source

Source: https://habr.com/ru/post/1497015/


All Articles