为什么这个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;
}
答案 0 :(得分:18)
如果从未输入while循环和“if语句”主体,则不会分配out参数。
可能是逻辑你知道将始终输入这些代码路径的情况。 编译器不知道这一点。编译器认为可以输入或跳过具有非常数条件的每个“if”和“while”。
在这种情况下,编译器可以进行更复杂的流分析。分析是“在'if'之前,结果为null或非null;如果为null,则'if'主体分配out参数。如果它不为null,那么唯一可能发生的方法是'如果' 'body指定了out参数,因此out参数被赋值。“
该级别的分析当然是可能的,但规范中描述的现有流分析算法具有一些不错的属性,即它快,易于理解, 易于实施,通常准确,而仅提供误报,而非假阴性。
答案 1 :(得分: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;
}
答案 2 :(得分:3)
if currentCard.CurrentSecond > startSecond
和
if result is null
他们将不会分配参数。
你可以这样做:
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;
}
答案 3 :(得分:2)
分配chunksize和bardatetime的两个地方都在某种控制语句中(while或if),编译器无法知道这些部分是否会输入或注释。
因此,对于这两个输出参数,就编译器所知,没有保证的分配。
答案 4 :(得分:1)
你可能不会设想那些没有设置的params,但是只要编译器知道(由于你有一个预检查循环)就可以在没有设置这些参数的情况下退出控制。
答案 5 :(得分:1)
如果result
为空,则永远不会分配bardatetime
。必须在方法返回之前设置声明为out
的参数。只需在方法开头将其初始化为默认值,它就可以正常工作。
答案 6 :(得分:0)
如果currentCard.CardSecond&lt; = startSecond,while循环将不会运行,结果将为null,并且永远不会设置值。编译器如何知道.CardSecond和startSecond将是什么?
答案 7 :(得分:0)
您可以尝试使用do {} while() - 循环替换while(){}循环。在这种情况下,将保证对齐。
答案 8 :(得分:0)
因为对于方法中的编译器,就像局部变量一样,输出参数最初被认为是未分配的,并且必须在使用其值之前明确赋值,现在检查GetBulk
的实现。
答案 9 :(得分:0)
在您输入功能时初始化它们。
答案 10 :(得分:0)
只是想指出使用ReSharper,插件本身会突出显示此代码的错误。