5

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

我的问题是我该怎么做?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;
        }
    }
4

3 回答 3

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();
于 2013-08-14T12:33:02.987 回答
3

好吧,您可以IEnumerator<T>改为存储一个,然后更改GetNextQuestion为:

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

但是,此时您实际上并没有为ExamorWizardStepService类添加任何值,您不妨IEnumerator<T>直接在Main. 请注意,您的Main方法本身有点奇怪 - 它在foreach循环更简单的地方重复了代码 - 而且您无条件地问了三个问题。

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

于 2013-08-14T12:30:41.850 回答
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;
    }
}
于 2013-08-14T12:32:50.873 回答