IEnumerable - 移动下一步

时间:2013-08-14 12:27:46

标签: c#

我有一个IEnumerable,我需要从中获取每个项目并逐个显示。显示不是一个连续的过程..即我应该获取一个项目并在UI上显示它,然后等待该项目的一些用户反馈,然后转到下一个项目。例如,从下面的代码中,我需要获取一个问题,然后将其显示给用户,然后用户点击进入,然后我继续提取下一个问题。

我的问题是我该怎么做? IEnumerable是实现此目的的最佳方式,还是应该恢复列表并开始存储索引并逐个递增?

请注意我使用的是.NET 3.5。

代码:

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;
        }
    }

3 个答案:

答案 0 :(得分:4)

是的,GetEnumerator()应该可以正常工作;虽然严格来说你需要处理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;
    }
}

还有:

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();
}

但是,由于您实际上并未每次都对结果进行测试,因此您还可以执行以下操作:

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();
}

或者作为最后的想法,也许只是:

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();

答案 1 :(得分:3)

您可以存储IEnumerator<T>,然后将GetNextQuestion更改为:

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

但是,此时您实际上并未使用ExamWizardStepService类添加任何值,您也可以直接在IEnumerator<T>中使用Main 。请注意,您的Main方法本身有点奇怪 - 它重复了代码,其中foreach循环会更简单 - 而且您无条件地提出三个问题。

请注意,如果你有一个IEnumerator<T>类型的字段作为字段,你可能想要实现IDisposable以便处理迭代器 - 这一切都有点混乱。

答案 2 :(得分:0)

试试这个:

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;
    }
}