Why is this C# code not compiling?
Why is this C# code not compiling?
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;
}
Errors:
The out parameter 'bardatetime' must be assigned to before control leaves the current method
The out parameter 'chunksize' must be assigned to before control leave开发者_Python百科s the current method
I can't think of a case where bardatetime and chunksize will end up unassigned..
Edit. I fixed this error by adjusting the code to a logically equivalent one. Honestly I wanted to avoid multiple assigments.
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;
}
If the while loop and "if statement" bodies are never entered then the out parameters are not assigned.
It might be the case that logically you know that those code paths will always be entered. The compiler does not know that. The compiler believes that every "if" and "while" that has a not-constant condition can be entered or skipped.
The compiler could in this case do a more sophisticated flow analysis. The analysis is "before the 'if', result is either null or not null; if it is null then the 'if' body assigns the out parameters. If it is not null then the only way that could have happened is if the 'while' body assigned the out parameters, therefore the out parameters are assigned."
That level of analysis is certainly possible, but the existing flow analysis algorithm described in the spec has some nice properties, namely that it is fast, easy to understand, easy to implement, usually accurate and only gives false positives, not false negatives.
Your out
params are not set up in all codepaths. If you skip the sections of code that are contingent on and while (currentCard.CurrentSecond <= startSecond)
and if (result = null)
then you must make some sensible default assignment to all of them.
You may know for a fact that the while
loop will execute at least once, but the compiler does not know this. In this case you may be able to replace that loop with a do {//logic} while (//condition);
alternative.
If you cannot do that, then this construct should enable the compiler to detect deterministic setting of the out
variables.
if (currentCard.CurrentSecond <= startSecond)
{
while (currentCard.CurrentSecond <= startSecond)
{
result = GetBulk(bufferId, out chunksize, out bardatetime);
}
}
else
{
result = null;
}
if currentCard.CurrentSecond > startSecond
and
if result is null
they out params will not be assigned.
You could do something like this:
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;
}
Both of the places where chunksize and bardatetime are assigned are inside some sort of control statement (while or if), which the compiler cannot know if those sections will be entered or note.
As such, there's no guaranteed assignment, as far as the compiler knows, for those two out parameters.
You may not conceive that those out params would not be set, but as far as the compiler knows it is possible (by virtue of you having a pre-check loop) for control to exit without those params being set.
If result
is null, bardatetime
will never be assigned. A parameter declared as out
must be set before the method returns. Just initialize it to a default value at the beginning of the method, it should work fine.
If currentCard.CardSecond <= startSecond the while loop won't run, result will be null and the values will never get set. How does the compiler know what .CardSecond and startSecond will be?
You can try to replace the while(){} loop with a do{}while()-loop. In this case the asignment would be guaranteed.
Because for the compiler within a method, just like a local variable, an output parameter is initially considered unassigned and must be definitely assigned before its value is used now check out your implementation of GetBulk
.
Initialize them as you enter the function.
Just wanted to point out that using ReSharper, the plugin itself would highlight what's wrong with this code.
精彩评论