[英]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.