繁体   English   中英

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

[英]Why is this C# code not compiling?

为什么这个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;
    }

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

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

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

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

您的out参数未在所有代码路径中设置。 如果跳过可能的和/ while (currentCard.CurrentSecond <= startSecond)if (result = null)的代码部分,那么你必须为所有代码做一些合理的默认赋值。

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

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

if (currentCard.CurrentSecond <= startSecond)
{
  while (currentCard.CurrentSecond <= startSecond)
  {
    result = GetBulk(bufferId, out chunksize, out bardatetime);
  }
}
else
{
  result = null;
}
if currentCard.CurrentSecond > startSecond 

if result is null

他们不会分配params。

你可以这样做:

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

分配chunksize和bardatetime的位置都在某种控制语句中(while或if),编译器无法知道是否输入这些部分或注释。

因此,就编译器所知,对于这两个输出参数,没有保证的分配。

您可能不会设想那些不会设置out参数,但只要编译器知道可以(由于您具有预检查循环)控制退出而不设置这些参数。

如果result为null,则永远不会分配bardatetime 声明为out的参数必须在方法返回之前设置。 只需在方法开头将其初始化为默认值,它应该可以正常工作。

如果currentCard.CardSecond <= startSecond,while循环将不会运行,结果将为null,并且将永远不会设置值。 编译器如何知道.CardSecond和startSecond是什么?

您可以尝试使用do {} while() - 循环替换while(){}循环。 在这种情况下,将保证对齐。

因为对于方法中的编译器,就像局部变量一样,输出参数最初被认为是未分配的,并且必须在使用其值之前明确赋值,现在检查GetBulk的实现。

在输入函数时初始化它们。

只想指出使用ReSharper ,插件本身会突出显示此代码的错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM