-1

重複の可能性:
デフォルトが 0 の場合、C# で値を int に代入する必要があるのはなぜですか?

Journal という不自然なアプリケーションを作成して、C# の学習を始めたところです。ジャーナル ファイルを解析する関数で、変数を宣言しましたDateTime currentEntryDate。新しいエントリを定義する行に到達するまで、値は取得されません。エントリ行に2回目に到達すると、変数はJournalEntry前のエントリのクラスのインスタンスを作成するために使用されます。

問題は、変数を使用するためのコードがコンパイルされないことです。

割り当てられていないローカル変数 'c​​urrentEntryDate' の使用

これは私には意味がありません。コンパイラを満足させるためだけに、無駄な初期値を変数に与える必要があるのでしょうか? 確かに私は何かを誤解したか、コードのどこかにエラーがあります。

Pastebin のコード: Journal.cs。関連する行を強調表示しました。

コード:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;

namespace Journal
{
    class Journal
    {
        public List<JournalEntry> Entries;

        private static readonly string EntryLineRegex =
            @"-- Entry: (?<title>.*) \((?<year>\d{4})-(?<month>\d{2})" +
            @"-(?<day>\d{2})\)";

        public static Journal FromFile(string filePath)
        {
            Journal returnValue = new Journal();

            StreamReader fileReader = new StreamReader(filePath);

            // Prepare variables for parsing the journal file.
            bool hitFirstEntry = false;
            DateTime currentEntryDate;
            string currentEntryTitle;
            StringBuilder currentEntryText = new StringBuilder();

            // Prepare a regular expression for the entry lines.
            Regex entryLineRegex = new Regex(EntryLineRegex);

            while (!fileReader.EndOfStream)
            {
                string line = fileReader.ReadLine();

                if (line.StartsWith("--"))
                {
                    // Is this the first entry encountered? If so, don't try to
                    // process the previous entry.
                    if (!hitFirstEntry)
                    {
                        hitFirstEntry = true;
                    }
                    else
                    {
                        // Create a JournalEntry with the current entry, then
                        // reset for the next entry.
                        returnValue.Entries.Add(
                            new JournalEntry(
                                currentEntryText.ToString(), currentEntryDate
                            )
                        );

                        currentEntryDate = new DateTime();
                        currentEntryText.Clear();
                    }

                    // Extract the new entry title and date from this line and
                    // save them.
                    Match entryMatch = entryLineRegex.Match(line);
                    GroupCollection matches = entryMatch.Groups;

                    currentEntryDate = new DateTime(
                        Convert.ToInt16(matches["year"].Value),
                        Convert.ToInt16(matches["month"].Value),
                        Convert.ToInt16(matches["day"].Value)
                    );

                    currentEntryTitle = matches["title"].Value;
                }
                else
                {
                    currentEntryText.Append(line);
                }
            }

            return returnValue;
        }
    }

    class JournalEntry
    {
        public string Text;
        public DateTime EntryDate;

        public JournalEntry(string text, DateTime entryDate)
        {
            this.Text = text;
            this.EntryDate = entryDate;
        }
    }
}
4

5 に答える 5

2

ここでの懸念は、コンパイラが入力の読み取り方法を把握するほど賢くなく、変数が初期化されない実行パスがあることelseですif。これを回避するには、定義時に初期化する必要がある場合があります。

于 2013-01-20T08:45:28.567 に答える
2

このようにループを再構築するのはどうですか? currentEntryDateこれにより、使用する前に に値があることが保証されます。

string line = fileReader.ReadLine();
while (line != null)
{
    // Extract the new entry title and date from this line and
    // save them.
    Match entryMatch = entryLineRegex.Match(line);
    GroupCollection matches = entryMatch.Groups;

    currentEntryDate = new DateTime(
        Convert.ToInt16(matches["year"].Value),
        Convert.ToInt16(matches["month"].Value),
        Convert.ToInt16(matches["day"].Value)
    );

    currentEntryTitle = matches["title"].Value;

    while ((line = fileReader.ReadLine()) != null && !line.StartsWith("--"))
    {
        currentEntryText.Append(line);
    }

    // Create a JournalEntry with the current entry, then
    // reset for the next entry.
    returnValue.Entries.Add(
        new JournalEntry(
            currentEntryText.ToString(), currentEntryDate
        )
    );

    currentEntryText.Clear();
}
于 2013-01-20T08:59:38.150 に答える
2

hitFirstEntryこの場合、コンパイラはとの間の「依存関係」を認識しませんcurrentEntryDate

hitFirstEntrywhenが に変更されるたびに が割り当てられることを「証明」できたとしてもtrue、 はその後currentEntryDateすぐに割り当てられ、(最短で) ループの次の反復まで初めて読み取らcurrentEntryDateれることはありません。コンパイラはそうではありません。その洗練された。たぶん、コードを書き直すことができます。

編集:コードの「最小」バージョンは次のとおりです。

        bool isFirstTime = true;
        DateTime localVarToBeAssigned;

        while (true)
        {
            if (isFirstTime)
            {
                isFirstTime = false;
            }
            else
            {
                // this reads the variable
                Console.WriteLine(localVarToBeAssigned);
            }

            // this assigns the variable
            localVarToBeAssigned = DateTime.Now;
        }
于 2013-01-20T08:59:54.487 に答える
1

あなたが本当にそれをインスタンス化したくない場合:

DateTime? currentEntryDate = null

疑問符は DateTime を null 可能にしますが、通常はそうではありません。

于 2013-01-20T08:56:24.713 に答える
-2

この変数はデフォルト値を持たないローカル変数を宣言し、スタックからメモリを取得します。このコードの行を変更して使用する前に、ローカル変数を初期化する必要があります。

currentEntryDate = new DateTime();

上の行が多すぎると、コードが機能します。

于 2013-01-20T08:56:22.410 に答える