In VB.NET on a boolean function if you run an Exit Function line will it return false?
That is correct, with the caveat that in VB the function name can also be a variable that is returned. If you've previously set that to true, it will return true.
More completely, in VB.Net, if I have a boolean function Foo() defined like so:
Public Function Foo() As Boolean
'...
...the body of that function has an implied variable also named Foo that matches the return type of the function — Boolean in this case, but Object if the return type is omitted (you should be using Option Strict, which requires a return type). This implied variable is initialized to use the default value for that type.
If you fail to Return a value from the function, whether via Exit Function or simply by reaching the end, this implied variable is returned instead. Therefore, a Boolean function will return False if you Exit Function early without making other changes, because that is the default value in the implied variable used with the function. But you could also set that variable to True first if you wanted, and then Exit Function would cause it to return True instead.
These days people don't often use the implied variable, but there are situations where it can save you a few lines of code without costing anything in clarity.
Regardless if it does or not (the compiler gives a null-reference warning only), you should still explicitly return false, if only for readability.
As long as you have not set that function to True before you exit
I always do "Return True" or "Return False" to exit a method instead of the exit statement.
Related
Edited: What and how it work? This is a kotlin dsl language.
fun ClassName.funcName(): (Type ) -> Type = {func body}
um this is one of the implementation I found, and also see the concrete syntax to this link: https://dzone.com/articles/the-complete-custom-gradle-plugin-building-tutoria
private fun CodeLinesExtension.buildFileFilter():
(File) ->
Boolean =
if (fileExtensions.isEmpty()) {
{ true }
} else {
{ fileExtensions.contains(it.extension) } // filter by extension
}
if you CALL this one as a arguments in ".filter(...)", what would happed in the "(File)" syntax, is it automatically receive an arguments?
someFiles.filter(CodeLinesExtension.buildFileFilter()).forEach{...}
There are many things at play here.
fun SomeClass.funcName() is the syntax for declaring extension functions. These are used just like regular methods of the class SomeClass, but can be defined outside of the class, and it's especially useful on classes that you don't control.
The return type of the function you mention is (File) -> Boolean. This expression describes a function type. In this specific case, it is the type of all functions that take a File as single argument, and return a Boolean.
This means that your buildFileFilter() function is an extension function that itself returns a function (File) -> Boolean.
As you can see in the function's body, inside the if statement, there are braces to define the blocks of the if-else ({ ... }), but also braces inside those blocks. This is because Kotlin uses braces for lambda expressions (literals for anonymous functions).
{ true } is a lambda expression that represents a function that may or may not take arguments, but returns true every time.
So this code:
if (fileExtensions.isEmpty()) {
{ true }
} else {
{ fileExtensions.contains(it.extension) } // filter by extension
}
returns either:
{ true } - a function that takes a File as argument and always returns true, or
{ fileExtensions.contains(it.extension) } - a function that takes a File as argument and returns whether fileExtensions contains the extension of the File that it receives (it is the implicit name for the File argument)
Note: the fact that these functions take a File as argument is inferred by the compiler based on the return type of buildFileFilter().
if you CALL this one as a arguments in ".filter(...)", what would happed in the "(File)" syntax, is it automatically receive an arguments?
filter() itself actually expects a function as argument. The function you pass to filter() is called a predicate, because it takes one element of the list as argument and returns a Boolean that says whether this element should be included in the resulting list.
So if you apply filter to a List<File>, the predicate expected by filter is exactly of type (File) -> Boolean (it says whether we should put this File item in the resulting collection).
Calling buildFileFilter() returns a function as we have seen, and the function is perfectly of the right type to use it in filter. The File argument of the function returned by buildFileFilter() will be given by the filter function itself when it calls your filter function.
I updated an AutoMapper V3.3.1 to V6.1.1 and much to my surprise, after putting all CreateMaps() in a profile, it actually worked perfectly right out of the gate – almost scary for me.
The problem that I am having is that it IS working with the code below as is suggested in the AutoMapper documentation:
Private Sub InitiatizeAutoMapper()
Mapper.Initialize(Function(cfg)
cfg.AddProfile(Of MappingProfile)()
End Function)
End Sub
But the code issues a warning:
Warning BC42105 Function '<anonymous method>' doesn't return a value on all code paths. A null reference exception could occur at run time when the result is used.
If I add a Return to the Lambda like:
Private Sub InitiatizeAutoMapper()
Mapper.Initialize(Function(cfg)
Return cfg.AddProfile(Of MappingProfile)()
End Function)
End Sub
I then get the following error:
Error BC30518 Overload resolution failed because no accessible 'Initialize' can be called with these arguments:
'Public Shared Overloads Sub Initialize(config As Action(Of IMapperConfigurationExpression))': Expression does not produce a value.
'Public Shared Overloads Sub Initialize(config As Action(Of IMapperConfigurationExpression))': Expression does not produce a value.
'Public Shared Overloads Sub Initialize(config As MapperConfigurationExpression)': Lambda expression cannot be converted to 'MapperConfigurationExpression' because 'MapperConfigurationExpression' is not a delegate type.
Now - if I make it a Sub instead of a function, it all works well with no errors like this:
Private Sub InitiatizeAutoMapper()
Mapper.Initialize(Sub(cfg)
cfg.AddProfile(Of MappingProfile)()
End Sub)
End Sub
I know that this will probably be a head-slapper but I am trying to follow the documentation and am afraid to release this into production in that I might be missing something.
EDIT:
I chose to break down the multiline lambda to make it a little easier for me, which also avails IntelliSense options quite handily for future enhancement. While it is probably not the "coolest" code, I find it very readable.
Private Sub InitiatizeAutoMapper()
Dim config As New Configuration.MapperConfigurationExpression : With config
.AddProfile(Of MappingProfile)()
End With
Mapper.Initialize(config)
End Sub
The whole point of a Function is that it returns something. In your first code snippet, what is your anonymous function returning? It isn't returning anything because it has no Return statement. There's no point arbitrarily adding a Return statement if you don't actually have anything to return and you can't return the result of AddProfile if that doesn't return anything itself. Basically, your lambda doesn't return anything and what do we call a method that doesn't return anything? It's a Sub.
You'll notice in the error message you posted that the Initialize method overloads that take a delegate as an argument are expecting an Action, not a Func. Action delegates are created with a Sub while a Function is used to create a Func delegate.
I am porting my template code to XTend. At some point I have this type of condition handling in a test case:
#Test
def xtendIfTest() {
val obj = new FD
if (true && obj?.property?.isNotNull) {
return
}
fail("Not passed")
}
def boolean isNotNull(Object o) {
return o != null
}
class FD {
#Accessors
String property
}
This works as expected as the property is null and the test will fail with "Not passed" message. But a simple change in the return type of isNotNull method to Boolean (wrapper):
def Boolean isNotNull(Object o) {
return o != null
}
fails with a NullPointerException. Examining the generated java code for this I can see that XTend is using an intermediate Boolean object expression and that is the cause of NPE. Am I missing the point of the XTend null safe operator (?.) or I can't use a method like this after the operator?
Thanks.
The operator behaves properly. The exception is thrown because of the usage of a Boolean in an if-expression, which requires auto-unboxing.
If you try the following:
#Test
def xtendIfTest() {
val Boolean obj = null
if (obj) {
return
}
fail("Not passed")
}
You will also run into a NullPointerException.
This is consistent with the Java Language Specification (https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.8) - when auto-unboxing is required this can yield a NullPointerException:
#Test
public void test() {
Boolean value = null;
if (value) { // warning: Null pointer access: This expression of type Boolean is null but requires auto-unboxing
// dead code
}
}
Hope that helps.
Short answer: Change the second null-safe call to a regular call.
I.e. change
obj?.property?.isNotNull
to this:
obj?.property.isNotNull
Long answer:
The docs describe the null-safe operator thusly:
In many situations it is ok for an expression to return null if a
receiver was null
That means the second call in your example, property?. won't even call isNotNull if the left side of the call was null. Instead, it will return null. So the conditional "effectively" evaluates to:
if (true && null) { // causes NPE when java tries to unbox the Boolean
(By the way - the true is superfluous in this context, but I'm keeping it just in case you had another condition to check - I'm assuming you're just simplifying it to true for this example.)
If you make the change I'm suggesting, obj?.property will be evaluated, then the result will be passed to isNotNull, evaluating to this:
if (true && isNotNull(null)) {
which returns the proper Boolean object that will be auto-unboxed as expected.
A Word of Caution
In your first form of isNotNull, i.e. the one returning primitive boolean, you should actually get a warning like "Null-safe call of primitive-valued feature isNotNull, default value false will be used".
This is because you're stretching the intent of the null-safe call, which is to return null without invoking the right side method if the left side of the operator was null. But if your isNotNull returns a primitive boolean, the whole expression obviously can't evaluate to null, so Xtend uses a default instead, which is false for booleans.
To emphasize the problem in a different way - it evaluates to false without calling isNotNull - that means even if you used a method isNull after the operator, it would still return false!
The docs also mention this behavior (albeit in general terms):
For primitive types the default value is returned (e.g. 0 for int).
This may not be what you want in some cases, so a warning will be
raised by default
So I recommend always using a non-primitive return value on the right-hand side of a null-safe call. But if you're going to convert the isNotNull to a regular call as I suggested, this rule doesn't apply, and either return type is fine.
From the Kotlin documentation:
If a function does not return any useful value, its return type is Unit. Unit is a type with only one value — Unit.VALUE. This value does not have to be returned explicitly:
fun printHello(name : String?) : Unit {
if (name != null)
print("Hello, $name!")
else
print("Hi there!")
// We don't need to write 'return Unit.VALUE' or 'return', although we could
}
What is the purpose of Unit-returning in functions? Why is VALUE there? What is this VALUE?
The purpose is the same as C's or Java's void. Only Unit is a proper type, so it can be passed as a generic argument etc.
Why we don't call it "Void": because the word "void" means "nothing", and there's another type, Nothing, that means just "no value at all", i.e. the computation did not complete normally (looped forever or threw an exception). We could not afford the clash of meanings.
Why Unit has a value (i.e. is not the same as Nothing): because generic code can work smoothly then. If you pass Unit for a generic parameter T, the code written for any T will expect an object, and there must be an object, the sole value of Unit.
How to access that value of Unit: since it's a singleton object, just say Unit
The main reason why Unit exists is because of Generic reasons.
Let's use the example from the Kotlin docs.
class Box<T>(t: T) {
var value = t
}
We can have
var box = Box(Unit)
This is why Unit returns a value so the Kotlin can infer it from the type passed into class initialization. Of course, you could also explicitly write it like this,
var box = Box<Unit>(Unit)
but all the same, it must have a return value.
Now, the void keyword in Java in Kotlin is Nothing. Nothing is the last but one type in the type hierarchy in Kotlin with the last one being Nothing? (Nullable Nothing). This does not return any value at all. Because it doesn't return any value at all, we can't pass it as a type in the above code.
var box = Box(Nothing) //This will return an Error
UNIT actually contains valuable information, it basically just means "DONE". It just returns the information to the caller, that the method has been finished. This is a real piece of information so it can be seen as the return value of a method.
In order to return a value from a VB.NET function one can assign a value to the "Functions Name" or use "return value."
I sometimes see these inter-mixed in the same function. Personally, I prefer the return.
My question is, what is the internal difference, if any, between the two?
The difference is that they DO DIFFERENT THINGS!
'Return value' does 2 things:
1. It sets the function return value at that point
2. It immediately exits the function
No further code in the function executes!
'Functionname = value' does 1 thing:
1. It sets the function return value at that point
Other code in the function continues to execute
This enables additional logic to refine or override the function return value
Huge difference folks. Remember it's not all about state, it's also about flow.
Let's take a look... Oddly the "functionName =" generates less IL?
Code:
Public Function Test() As String
Test = "Test"
End Function
Public Function Test2() As String
Return "Test"
End Function
IL:
.method public static string Test() cil managed
{
.maxstack 1
.locals init (
[0] string Test)
L_0000: nop
L_0001: ldstr "Test"
L_0006: stloc.0
L_0007: ldloc.0
L_0008: ret
}
.method public static string Test2() cil managed
{
.maxstack 1
.locals init (
[0] string Test2)
L_0000: nop
L_0001: ldstr "Test"
L_0006: stloc.0
L_0007: br.s L_0009
L_0009: ldloc.0
L_000a: ret
}
There is probably no difference. IIRC, the compiler generated IL converts them both into Return statements unless there is additional usage of a _returnValue variable.
The readability of the FunctionName assignment is poor in my opinion, and an example of a bad VB6 habit. I prefer the _returnValue (NOT RETVAL) variable method also.
Doing the following is only provided for Visual Basic 6.0 developers to easily port code over:
Public Function MyFunction() As String
MyFunction = "Hello"
End Function
I would definitely not recommend keeping doing it if your project includes anyone who hasn't worked with Visual Basic 6.0, as this syntax will be confusing.
When Tools/Options/Text Editor/All Languages/Code Lens is activated, the Reference Count shows above each Sub, Function, or Property statement.
"Return Value" seems better than "assigning a value to the Functions Name". In the latter case, "Code Lens" produces an inflated Reference Count.
' Code Lens reports "0 references" here for Sub Rosa().
Public Sub Rosa()
Diagnostics.Debug.WriteLine(Test())
Diagnostics.Debug.WriteLine(Test2())
End Sub
' Code Lens reports "2 references" here for Function Test().
Public Function Test() As String
Test = "Test" ' Code Lens counts this as a reference.
End Function
' Code Lens reports "1 reference" here for Function Test2().
Public Function Test2() As String
Dim strTest2 as String = "Test"
Return strTest2 ' Code Lens does NOT count this as a reference.
End Function
99 times out of 100 I'll use "return value".
Every once in a while I'll have a function where the other type not only allows me to save a variable declaration, but do it in a way that actually significantly clarifies the function. Usually this happens when I would want to name the return value the same as the function anyway, and often these are recursive functions; something about that construct lends it to the implicit return variable. However, that scenario is extremely rare. I don't know if I have any functions using implicit return variables at all in my current project.
Having read that the Return Value syntax was the One True .NET Way Of Doing Things I thought "OK, we'll do it that way then". Then I wrote a function which I knew, hand on heart KNEW, returned either a value from a Return statement or alternatively an Exception under all circumstances, and still got a compiler warning that the function "doesn't return a value on all paths".
Thankfully I came across the Stack Overflow question How can I make this function not generate a “doesn't return a value on all paths” warning? which explained why; adding a default value assignment to the procedure name at the head of the function prevented the warning in my case as well.
Consequently, even though I'll continue to use the Return Value syntax simply for the sake of syntax consistency, I'll also be assigning a default value to the function name just to prevent the possibility of cluttering up the compile process with bogus warnings.
its quite handy when working with 3rd party factories(_hsf), you can avoid declaring return variables
Public Function CreateExtremum(iShape As INFITF.Reference, iDir1 As HybridShapeTypeLib.HybridShapeDirection, iSide1 As Integer, iDir2 As HybridShapeTypeLib.HybridShapeDirection, iSide2 As Integer, iDir3 As HybridShapeTypeLib.HybridShapeDirection, iSide3 As Integer) As HybridShapeTypeLib.HybridShapeExtremum
CreateExtremum = _hsf.AddNewExtremum(iShape, iDir1, iSide1)
CreateExtremum.Direction2 = iDir2
CreateExtremum.ExtremumType2 = iSide2
CreateExtremum.Direction3 = iDir3
CreateExtremum.ExtremumType3 = iSide3
CreateExtremum.Compute()
End Function