3

この C# コードがコンパイルされないのはなぜですか?

public static Dictionary<short, MemoryBuffer> GetBulkCustom(int bufferId,
    int startSecond,out int chunksize, out int bardatetime)
{
    //const string _functionName = "GetNextBulkWatchData";

    UserSeriesCard currentCard = GetUserSeriesCard(bufferId);

    Dictionary<short, MemoryBuffer> result = null;

    while (currentCard.CurrentSecond <= startSecond)
        result = GetBulk(bufferId, out chunksize, out bardatetime);

    if (result == null)
    {
        result = currentCard.UserBuffer;
        chunksize = currentCard.ChunkSize;
        bardatetime = currentCard.CurrentBarDateTime;
    }
    return result;
}

エラー:

The out parameter 'bardatetime' must be assigned to before control leaves the current method
The out parameter 'chunksize' must be assigned to before control leaves the current method

bardatetime と chunksize が未割り当てになるケースは考えられません..

編集します。コードを論理的に同等のものに調整することで、このエラーを修正しました。正直なところ、複数の割り当ては避けたかったのです。

public static Dictionary<short, MemoryBuffer> GetBulkCustom(int bufferId, int startSecond,out int chunksize, out int bardatetime )
    {
        const string _functionName = "GetNextBulkWatchData";

        UserSeriesCard currentCard = GetUserSeriesCard(bufferId);

        Dictionary<short, MemoryBuffer> result = null;
        chunksize = currentCard.ChunkSize;
        bardatetime = currentCard.CurrentBarDateTime;

        while (currentCard.CurrentSecond <= startSecond)
            result = GetBulk(bufferId, out chunksize, out bardatetime);

        if (result == null)
            result = currentCard.UserBuffer;

        return result;
    }
4

11 に答える 11

18

while ループと "if ステートメント" 本体が入力されない場合、out パラメータは割り当てられません。

これらのコード パスが常に入力されることが論理的にわかっている場合があります。コンパイラはそれを知りません。コンパイラは、一定でない条件を持つすべての「if」および「while」を入力またはスキップできると考えています。

この場合、コンパイラはより高度なフロー分析を行うことができます。分析は「'if' の前に行われ、結果は null であるか、null ではないかのいずれかです。null の場合は、'if' 本体が out パラメータを割り当てます。null でない場合、発生する唯一の方法は、' while' body に out パラメータが割り当てられたため、out パラメータが割り当てられます。

そのレベルの分析は確かに可能ですが、仕様に記載されている既存のフロー分析アルゴリズムにはいくつかの優れた特性があります。つまり、高速で、理解やすく、実装しやすく通常は正確であり、偽陰性ではなく偽陽性のみを示します

于 2010-09-27T13:51:18.807 に答える
5

outパラメータがすべてのコードパスで設定されているわけではありません。while (currentCard.CurrentSecond <= startSecond)andに依存するコードのセクションをスキップする場合はif (result = null)、それらすべてに適切なデフォルトの割り当てを行う必要があります。

whileループが少なくとも 1 回実行されることはわかっているかもしれませんが、コンパイラはこれを知りません。この場合、そのループを別のものに置き換えることができる場合がありますdo {//logic} while (//condition);

それができない場合は、この構成により、コンパイラがout変数の決定論的設定を検出できるようになります。

if (currentCard.CurrentSecond <= startSecond)
{
  while (currentCard.CurrentSecond <= startSecond)
  {
    result = GetBulk(bufferId, out chunksize, out bardatetime);
  }
}
else
{
  result = null;
}
于 2010-09-27T13:50:27.997 に答える
3
if currentCard.CurrentSecond > startSecond 

if result is null

それらの out パラメータは割り当てられません。

次のようなことができます。

public static Dictionary<short, MemoryBuffer> GetBulkCustom(int bufferId, int startSecond,out int chunksize, out int bardatetime )
{
    //const string _functionName = "GetNextBulkWatchData";


    UserSeriesCard currentCard = GetUserSeriesCard(bufferId);

    Dictionary<short, MemoryBuffer> result = null;

    // initialize with a -1
    bardatetime = -1;
    chunksize = -1;   

    while (currentCard.CurrentSecond <= startSecond)
        result = GetBulk(bufferId, out chunksize, out bardatetime);

    if (result == null)
    {
        result = currentCard.UserBuffer;
        chunksize = currentCard.ChunkSize;
        bardatetime = currentCard.CurrentBarDateTime;
    }

    return result;
}
于 2010-09-27T13:51:13.613 に答える
2

chunksize と bardatetime が割り当てられる場所は両方とも、ある種の制御ステートメント (while または if) 内にあり、コンパイラーはそれらのセクションが入力されるかどうかを認識できません。

そのため、コンパイラが知る限り、これら 2 つの out パラメーターに対する保証された割り当てはありません。

于 2010-09-27T13:51:20.803 に答える
1

これらの out パラメーターが設定されていないとは考えられないかもしれませんが、コンパイラーが知る限り、(事前チェック ループがあるため) これらのパラメーターが設定されずに制御が終了する可能性があります。

于 2010-09-27T13:51:17.510 に答える
1

resultnull の場合、bardatetime割り当てられません。outメソッドが戻る前に設定する必要があるとして宣言されたパラメーター。メソッドの先頭でデフォルト値に初期化するだけで、正常に動作するはずです。

于 2010-09-27T13:51:24.170 に答える
0

メソッド内のコンパイラーの場合、ローカル変数と同様に、出力パラメーターは最初は未割り当てと見なされ、その値を使用する前に確実に割り当てる必要があるため、の実装を確認してくださいGetBulk

于 2010-09-27T13:54:16.773 に答える
0

関数に入るときにそれらを初期化します。

于 2010-09-27T13:55:28.803 に答える
0

while(){} ループを do{}while() ループに置き換えることができます。この場合、割り当ては保証されます。

于 2010-09-27T13:53:46.883 に答える
0

ReSharperを使用すると、プラグイン自体がこのコードの問題点を強調することを指摘したかっただけです。

于 2010-09-27T13:58:41.980 に答える
0

currentCard.CardSecond <= startSecond の場合、while ループは実行されず、結果は null になり、値は設定されません。コンパイラは .CardSecond と startSecond が何であるかをどのように認識しますか?

于 2010-09-27T13:51:31.340 に答える