Often those sorts of variables are used to maintain iterators. C# has these built directly into the language via the yield
keyword. Here's an example:
IEnumerable<int> TimesTable(int table)
{
for (int i=0 ; i<12 ; i++)
{
yield return i * table;
}
}
In this example, we create the values in the n times table where n is specified by the caller. We can use this anywhere an iterator is used, such as in a foreach
loop:
foreach (var value in TimesTable(3))
{
Console.Write(""+ value + " ");
}
...which produces:
3 6 9 12 15 18 21 24 27 30 33 36
In C++, this might have used static variables like the ones you described from VB (I'm not a VB guy so I don't know the VB syntax):
int TimesTable(int table) {
static i = 1;
if (i == 12) {
i = 1;
}
return i++ * table;
}
The C# version is better than the C++ (or VB) equivalent becuase the iterator can be cancelled early and there can be multiple iterators active at any given time. These things are not true for the C++ version without more work from the developer. On the downside, it means that the only time anything like a static variable is valid in C# is during an iterator implementation, and the value does not persist beyond that scope.
I hope that is of some use to you.