5

各項目を取得して 1 つずつ表示する必要がある IEnumerable があります。表示は継続的なプロセスではありません。つまり、1 つのアイテムを取得して UI に表示し、そのアイテムに対するユーザーのフィードバックを待ってから、次のアイテムに移動する必要があります。たとえば、以下のコードでは、質問を取得してユーザーに表示し、ユーザーが Enter キーを押して、次の質問の取得に進む必要があります。

私の質問はどうすればいいですか?IEnumerable はこれを達成するための最良の方法ですか、それともリストに戻ってインデックスの保存を開始し、1 つずつインクリメントする必要がありますか?

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

ただし、その時点では、実際にはExamまたはWizardStepServiceクラスで値を追加していないためIEnumerator<T>、 in で直接使用することもできますMainMainメソッド自体が少し奇妙であることに注意してください-foreachループがより単純になるコードを繰り返しています-無条件に3つの質問をしています。

フィールドとして an を持つ型がある場合は、イテレータも破棄するために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 に答える