为什么这个C#代码没有编译?

mus*_*bar 3 c# compilation out-parameters

为什么这个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;
}
Run Code Online (Sandbox Code Playgroud)

错误:

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
Run Code Online (Sandbox Code Playgroud)

我想不出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;
    }
Run Code Online (Sandbox Code Playgroud)

Eri*_*ert 18

如果从未输入while循环和"if语句"主体,则不分配out参数.

从逻辑上讲,您可能知道始终会输入这些代码路径.该编译器不知道.编译器认为可以输入或跳过具有非常数条件的每个"if"和"while".

在这种情况下,编译器可以进行更复杂的流分析.分析是"在'if'之前,结果为null或非null;如果为null,则'if'主体分配out参数.如果它不为null,那么唯一可能发生的方法是'如果' 'body指定了out参数,因此out参数被赋值."

这种分析水平当然是可能的,但规范中描述的现有流量分析算法具有一些很好的特性,即它快速,易于理解,易于实现,通常是准确的,并且只给出误报,而不是假阴性.

  • 我只知道我正在和编译器说话:D (6认同)

Ste*_*end 5

您的out参数未在所有代码路径中设置.如果你跳过上和队伍的代码段while (currentCard.CurrentSecond <= startSecond)和if (result = null)那么你就必须做出一些合理的默认分配给所有的人.

您可能知道while循环将至少执行一次,但编译器不知道这一点.在这种情况下,您可以使用do {//logic} while (//condition);替代方案替换该循环.

如果你不能这样做,那么这个结构应该使编译器能够检测out变量的确定性设置.

if (currentCard.CurrentSecond <= startSecond)
{
  while (currentCard.CurrentSecond <= startSecond)
  {
    result = GetBulk(bufferId, out chunksize, out bardatetime);
  }
}
else
{
  result = null;
}
Run Code Online (Sandbox Code Playgroud)