I am currently working on converting some VB source code over to C#. While I understand there are converters to automate this, and that I could actually use this particular dll without rewriting it, I'm doing it partially so I can understand VB better. Not so much as to expect to write it, but it's at least helping me to be able to read it.
In doing this though, I've come across something that is quite confusing. The following code snippets are examples, but I've seen it throughout the program.
VB Source Code:
Friend Function AllocateObjectNumber() As Long
AllocateObjectNumber = _nextFreeObjectNumber
_nextFreeObjectNumber += 1
_objectAllocatedCount += 1
End Function
My translated C# Code:
internal long AllocateObjectNumber()
{
cvNextFreeObjectNumber += 1;
cvObjectAllocatedCount += 1;
return cvNextFreeObjectNumber;
}
What I'm not understanding is the flow control that VB uses. I understand that AllocateObjectNumber += 1 is used in place of return cvNextFreeObjectNumber, but if this line comes before the incrementing of the two variables, then how is that code not considered unreachable? Based on my C# understanding, the first line in this method would immediately return to the calling method, and this whole method would basically act as a pseudo-Property.
Any helpful explanations?
The VB approach is more similar to storing the value in a temporary variable:
internal long AllocateObjectNumber()
{
var nextNumber = _nextFreeObjectNumber
cvNextFreeObjectNumber += 1;
cvObjectAllocatedCount += 1;
return nextNumber;
}
In VB the function = value syntax doesn't do a return - so the code after can keep running. When that method reaches the end, then the value you used becomes the 'return' value for whatever called it in the first place.
You can use the function = value syntax multiple times in the same method as a way of returning a different result in different conditions without needing the temporary variable I used in my example.
Based on my C# understanding, the first line in this method would immediately return to the calling method
But it’s not C# code, it’s VB code. AllocateObjectNumber = _nextFreeObjectNumber does not return, it just assigns a return value. The actual return is at the end of the method.
Most people would actually write the VB code identical to the C# code, i.e. using Return explicitly. The assign-to-method-name style is a remnant of older VB versions where it was the only way of returning a value from a function. In VB.NET, you can use both.
Related
If you compile the following code:
private async Task<int> M()
{
return await Task.FromResult(0);
}
And then decompile it (I used dotPeek) and examine the all-important MoveNext method, you will see a bool variable declared near the beginning; dotPeek chose "flag" for me.
bool flag = true;
In this case, you will see one subsequent consumer of that variable, in the default case statement after initiating the first async call:
if (!awaiter.IsCompleted)
{
this.\u003C\u003E1__state = 0;
this.\u003C\u003Eu__\u0024awaiter11 = awaiter;
this.\u003C\u003Et__builder.AwaitUnsafeOnCompleted<TaskAwaiter<int>, Program.\u003CP\u003Ed__10>(ref awaiter, ref this);
flag = false;
return;
}
I've tried half a dozen more complicated examples than my initial one, and they are consistent in only assigning to this variable before exiting the method. So in other words, in all the cases I've tried so far, this variable is not only never consumed, but is only given a non-initial value immediately before returning from the method -- a point in time where the assignment is definitionally useless.
As background, I am enjoying the process of trying to implement async/await in Javascript via a C# -> JS cross-compiler. I'm trying to understand in what situation I need to consider the utility of this flag. At face, it seems spurious and therefore I should ignore it. However, I'd like to understand why the C# compiler introduces this variable -- I suspect there are more complicated expressions that consume this variable in a useful way.
To put is succinctly: Why does the C# compiler generate this flag variable?
The following comment posted under the question describes its use:
Wrap your await statement in a try-finally block and set some variable inside the finally block. I don't fully understand what the IL logic is doing but I just did a quick look and it looks like it uses that flag variable to check when to execute code inside the finally block.
–Ilian Pinzon
Also Stephen Cleary adds some useful information for the interested reader. He recommends this blog series and in particular this blog post.
#IlianPinzon has the correct answer. This is explained in more detail in one of Jon Skeet's eduasync posts. Since you're writing a cross-compiler, I strongly recommend reading that whole series.
–Stephen Cleary
This is the first time I face a problem like this. Not being this my profession but only my hobby, I have no previous references.
In my program I have added one by one several functions to control a machine. After I added the last function (temperature measurement), I have started experiencing problems on other functions (approx. 8 of them running all together. The problem I am experiencing is on a chart (RPM of a motor) that is not related to this function but is affected by it. You see the difference between these two charts with and without the temperature measurement running. The real speed of the motor is the same in both charts but in the second one I loose pieces on the fly because the application slows down.
Without the temperature function.
With the temperature function
Particularly this function is disturbing the above control and I think is because the work load is becoming heavy for the application and or because I need sampling so there is some time waiting to get them:
private void AddT(decimal valueTemp)
{
sumTemp += valueTemp;
countTemp += 1;
if (countTemp >= 20) //take 20 samples and make average
{
OnAvarerageChangedTemp(sumTemp / countTemp);
sumTemp = 0;
countTemp = 0;
}
}
private void OnAvarerageChangedTemp(decimal avTemp)
{
float val3 = (float)avTemp;
decimal alarm = avTemp;
textBox2.Text = avTemp.ToString("F");
if (alarm > 230)
{
System.Media.SoundPlayer player = new System.Media.SoundPlayer();
player.Stream = Properties.Resources.alarma;
player.Play();
timer4.Start();
}
else
{
timer4.Stop();
panel2.BackColor = SystemColors.Control;
}
}
I am wondering if running this function on a different thread would solve the problem and how I can do that? Or if there is a different way to solve the problem.Sample code will be appreciated.
Update, added method call.
This is how I call the method AddT
if (b != "")
{
decimal convTemp; //corrente resistenza
decimal.TryParse(b, out convTemp);
AddT(convTemp);}
This is how I receive the data from the serial and pass it to the class that strips out unwonted chars and return values to the different variables.
This is the class that strips out the unwonted chars and return the values.
And this is how I manage the serial incoming data. Please do not laugh at me after seeing my coding. I do a different job and I am learning on my own.
It's very hard to tell if there's anything wrong and what it might be - it looks like subtle problem.
However, it might be easier to get a handle on these things if you refactor your code. There are many things in the code you've shown that make it harder than necessary to reason about what's happening.
You're using float and decimal - float isn't that accurate but small and fast; decimal (tries) to be precise but especially is predictable since it rounds errors the way a human might in base-10 - but it is quite slow, and is usually intended for calculations where precise reproducibility is necessary (e.g. financial stuff). You should probably use double everywhere.
You've got useless else {} code in the Stripper class.
Your Stripper is an instatiable class, when it should simply be a static class with a static method - Stripper is stateless.
You're catching exceptions just to rethrow them.
You're using TryParse, and not checking for success. Normally you'd only use TryParse if you (a) expect parsing to fail sometimes, and (b) can deal with that parse failure. If you don't expect failure or can't deal with it, you're better off with a crash you learn about soon than a subtly incorrect values.
In stripper, you're duplicating variables such as _currentMot, currentMot, and param4 but they're identical - use only the parameter, and give it a logical name.
You're using out parameters. It's almost always a better idea to define a simple struct and return that instead - this also allows you to ensure you can't easily mix up variable names, and it's much easier to encapsulate and reuse functionality since you don't need to duplicate a long call and argument definition.
Your string parsing logic is too fragile. You should probably avoid Replace entirely, and instead explicitly make a Substring without the characters you've checked for, and you have some oddly named things like test1 and test2 which refer to a lastChar that's not the last character - this might be OK, but better names can help keep things straight in your head too.
You have incorrect code comments (decimal convTemp; //corrente resistenza). I usually avoid all purely technical code comments; it's better to use descriptive variable names which are another form of self-documenting code but one in which the compiler can at least check if you use them consistently.
Rather that return 4 possibly empty values, your Stripper should probably accept a parameter "sink" object on which it can call AddT AddD and AddA directly.
I don't think any of the above will fix your issue, but I do believe they're help keep your code a little cleaner and (in the long run) make it easier to find the issues.
your problem is in the parsing of the values you have
decimal.TryParse(a, out convRes);
AddA(convRes);
and don't check for failed values you only accept the value if it returns true
if(decimal.TryParse(a, out convRes))
{
AddA(convRes);
}
you may have more errors but this one is making you process 0 values every time the TryParse fails.
In C# it's conventional to write in a fairly objective manner, like so:
MyObj obj = new MyObj();
MyReturn ret = obj.DoSomething();
AnotherReturn rett = ret.DoSomethingElse();
I could just write the above like this:
AnotherReturn rett = new MyObj().DoSomething().DoSomethingElse();
However, how does the stackframe work when you have a bunch of function calls in a sequence like this? The example is fairly straightforward but imagine if I've got 50+ function calls chained (this can possibly happen in the likes of JavaScript (/w jQuery)).
My assumption was that, for each function call, a return address is made (to the "dot"?) and the return value (a new object with other methods) is then immediately pumped into the next function call at that return address. How does this work w.r.t. getting to the overall return value (in this example the return address will assign the final function value to rett)? If I kept chaining calls would I eventually overflow? In that case, is it considered wiser to take the objective route (at the cost of "needless" memory assignment?).
It's exactly the same as if you called each method on a separate line, assigning the return value to a variable each time and then using that variable to call the next method.
So your two samples are the same, effectively.
Do you have Reflector? You could try the two methods and inspect the generated IL code to see exactly what differences there are.
Although the 2 calls are same but if you have lot of "Dots" then somewhere it is a code smell (Law of Demeter).
See below discussion
Take a look at this VB.NET code:
list = GeoController.RegionByCountry(country, language)
Region.allByLanguage(key) = list
In C#, I could write this in one line:
Region.allByLanguage[key] =
(list = GeoController.RegionByCountry(country, language))
Is there a way to make this a one-liner in VB.NET, like I can in C#?
EDIT: You all must need some sleep, or else you might be thinking a little harder.
Region.allByLanguage is a cache.
Here's the context:
Dim list As IEnumerable(Of Region)
Dim key = Region.CacheKey(country, language)
If Region.allByLanguage.ContainsKey(key) Then
list = Region.allByLanguage(key)
Else
list = GeoController.RegionsByCountryAndLanguage(country, language)
Region.allByLanguage(key) = list
End If
Return list
How can you tell me that's not verbose code? Shudders.
Heck, if this was a C# team, I'd just write:
return Region.allByLanguage.ContainsKey(key) ?
Region.allByLanguage[key] :
(Region.allByLanguage[key] = GeoController.RegionsByCountryAndLanguage(country, language));
Do you actually need access to the list instance also? If not, why not just write it like this?
Region.allByLanguage[key] = GeoController.RegionByCountry(country, language));
Your syntax seems strange for C# also, and I don't think many would write that code that way.
Also, it's no goal in itself to reduce the number of lines of code, if it makes the code less readable as you are trying to do in this case.
If you are assigning to both Region.allByLanguage[key] and list, I would prefer two lines of code if I ever were to read your code. Merging both assignments on one line of code seems forced at best, and might have the reader not realize that list is assigned as well as Region.allByLanguage[key].
As an alternative, unless your cache is massive or doing something heavyweight, I would just change the code to something like this:
Dim key = Region.CacheKey(country, language)
If not Region.allByLanguage.ContainsKey(key) Then
Region.allByLanguage(key) = GeoController.RegionsByCountryAndLanguage(country, language)
End If
Return Region.allByLanguage(key)
This way you can avoid the need for single line assignment, and you still reduce the lines of code. You can refactor it back out if performance becomes a problem.
In VB.NET, you cannot assign to a variable and assign that same variable to another variable.
In your code, you're assigning GeoController.RegionByCountry(country, language) to list and then assigning list to Region.allByLanguage[key]
In most cases, this is not a good thing to do as it makes your code more difficult to read.
If you are going to use the list variable later in the subroutine, it is better to go the VB way; explicitly assign the list and then assign it to the region. If you're not going to use it later then just assign result of GeoController.RegionByCountry(country, language) straight away and skip the temporary assignment to the list variable.
If you insist, however on a 'one-liner', you can use this code I was forced to write when I attempted porting some C# code to VB.NET some time ago:
<Extension()> Public Function AssignAndReturn(Of T)(ByVal source As T, ByRef target As T) As T
target = source
Return target
End Function
You can use it like so:
Region.allByLanguage(key) = GeoController.RegionByCountry(country, language).AssignAndReturn(list)
It evaluates the GeoController.RegionByCountry(country, language), assigns it to the list and then returns the result; which is the list.
When writing an API or reusable object, is there any technical reason why all method calls that return 'void' shouldn't just return 'this' (*this in C++)?
For example, using the string class, we can do this kind of thing:
string input= ...;
string.Join(input.TrimStart().TrimEnd().Split("|"), "-");
but we can't do this:
string.Join(input.TrimStart().TrimEnd().Split("|").Reverse(), "-");
..because Array.Reverse() returns void.
There are many other examples where an API has lots of void-returning operations, so code ends up looking like:
api.Method1();
api.Method2();
api.Method3();
..but it would be perfectly possible to write:
api.Method1().Method2().Method3()
..if the API designer had allowed this.
Is there a technical reason for following this route? Or is it just a style thing, to indicate mutability/new object?
(x-ref Stylistic question concerning returning void)
EPILOGUE
I've accepted Luvieere's answer as I think this best represents the intention/design, but it seems there are popular API examples out there that deviate from this :
In C++ cout << setprecision(..) << number << setwidth(..) << othernumber; seems to alter the cout object in order to modify the next datum inserted.
In .NET, Stack.Pop() and Queue.Dequeue() both return an item but change the collection too.
Props to ChrisW and others for getting detailed on the actual performance costs.
Methods that return void state more clearly that they have side effects. The ones that return the modified result are supposed to have no side effects, including modifying the original input. Making a method return void implies that it changes its input or some other internal state of the API.
If you had Reverse() return a string, then it wouldn't be obvious to a user of the API whether it returned a new string or the same-one, reversed in-place.
string my_string = "hello";
string your_string = my_string.reverse(); // is my_string reversed or not?
That is why, for instance, in Python, list.sort() returns None; it distinguishes the in-place sort from sorted(my_list).
Is there a technical reason for following this route?
One of the C++ design guidelines is "don't pay for features you don't use"; returning this would have some (slight) performance penalty, for a feature which many people (I, for one) wouldn't be inclined to make use of.
The technical principal that many others have mentioned (that void emphasizes the fact the function has a side-effect) is known as Command-Query Separation.
While there are pros and cons to this principle, e.g., (subjectively) clearer intent vs. more concise API, the most important part is to be consistent.
I'd imagine one reason might be simplicity. Quite simply, an API should generally be as minimal as possible. It should be clear with every aspect of it, what it is for.
If I see a function that returns void, I know that the return type is not important. Whatever the function does, it doesn't return anything for me to work with.
If a function returns something non-void, I have to stop and wonder why. What is this object that might be returned? Why is it returned? Can I assume that this is always returned, or will it sometimes be null? Or an entirely different object? And so on.
In a third-party API, I'd prefer if that kind of questions just never arise.
If the function doesn't need to return anything, it shouldn't return anything.
If you intend your API to be called from F#, please do return void unless you're convinced that this particular method call is going to be chained with another nearly every time it's used.
If you don't care about making your API easy to use from F#, you can stop reading here.
F# is more strict than C# in certain areas - it wants you to be explicit about whether you're calling a method in order to get a value, or purely for its side-effects. As a result, calling a method for its side-effects when that method also returns a value becomes awkward, because the returned value has to be explicitly ignored in order to avoid compiler errors. This makes "fluent interfaces" somewhat awkward to use from F#, which has its own superior syntax for chaining a series of calls together.
For example, suppose we have a logging system with a Log method that returns this to allow for some sort of method chaining:
let add x y =
Logger.Log(String.Format("Adding {0} and {1}", x, y)) // #1
x + y // #2
In F#, because line #1 is a method call that returns a value, and we're not doing anything with that value, the add function is considered to take two values and return that Logger instance. However, line #2 not only also returns a value, it appears after what F# considers to be the "return" statement for the function, effectively making two "return" statements. This will cause a compiler error, and we need to explicitly ignore the return value of the Log method to avoid this error, so that our add method has only a single return statement.
let add x y =
Logger.Log(String.Format("Adding {0} and {1}", x, y)) |> ignore
x + y
As you might guess, making lots of "Fluent API" calls that are mainly about side-effects becomes a somewhat frustrating exercise in sprinkling lots of ignore statements all over the place.
You can, of course, have the best of both worlds and please both C# and F# developers by providing both a fluent API and an F# module for working with your code. But if you're not going to do that, and you intend your API for public consumption, please think twice before returning this from every single method.
Besides the design reasons, there is also a slight performance cost (both in speed and space) for returning this.