开发者

VB.Net: Is there something to be gained by using the Function itself to hold the return value instead of declaring a local variable?

开发者 https://www.devze.com 2023-01-22 14:38 出处:网络
What\'s best practice (in VB.Net): Function GetSomething() as String GetSomething = \"Here\'s your string\"

What's best practice (in VB.Net):

Function GetSomething() as String
    GetSomething = "Here's your string"
End Function

or

Function GetSomething() as String
    Dim returnString as String = "Here's your string"
    Return returnString
End Function

Obviously, neither of these implementations make any sense, but they're just meant to illustrate my point. Is there anything to be gained by using GetSomething itself to store the return value instead of declaring returnString locally and then returning that (does it avoid having an extra string allocated/instantiated - and if so, are there any perf开发者_如何学Goormance/memory benefits)?


Interesting question. I ran this:

Function GetSomething1() As String
    GetSomething1 = "Here's your string"
End Function

Function GetSomething2() As String
    Dim returnString As String = "Here's your string"
    Return returnString
End Function

through IL DASM and here are the results:

Debug build:

.method public instance string  GetSomething1() cil managed
{
  // Code size       9 (0x9)
  .maxstack  1
  .locals init ([0] string GetSomething1)
  IL_0000:  nop
  IL_0001:  ldstr      "Here's your string"
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  ret
} // end of method Form1::GetSomething1

.method public instance string  GetSomething2() cil managed
{
  // Code size       13 (0xd)
  .maxstack  1
  .locals init ([0] string GetSomething2,
           [1] string returnString)
  IL_0000:  nop
  IL_0001:  ldstr      "Here's your string"
  IL_0006:  stloc.1
  IL_0007:  ldloc.1
  IL_0008:  stloc.0
  IL_0009:  br.s       IL_000b
  IL_000b:  ldloc.0
  IL_000c:  ret
} // end of method Form1::GetSomething2

Release build:

.method public instance string  GetSomething1() cil managed
{
  // Code size       8 (0x8)
  .maxstack  1
  .locals init ([0] string GetSomething1)
  IL_0000:  ldstr      "Here's your string"
  IL_0005:  stloc.0
  IL_0006:  ldloc.0
  IL_0007:  ret
} // end of method Form1::GetSomething1

.method public instance string  GetSomething2() cil managed
{
  // Code size       8 (0x8)
  .maxstack  1
  .locals init ([0] string GetSomething2,
           [1] string returnString)
  IL_0000:  ldstr      "Here's your string"
  IL_0005:  stloc.1
  IL_0006:  ldloc.1
  IL_0007:  ret
} // end of method Form1::GetSomething2

You'll note that there are more operations in the debug build but not in the release build.

So to answer your question, it seems that declaring the variable costs a little bit extra in debug builds, which is often the case (optimization not turned on or is not as much optimized). But in the release build (as expected) the optimizer removes this unnecessary operation.


Try it both ways then use .Net Reflector to see if the generated IL is different.


I prefer having explicit exit points so I always use Return. Furthermore, I don’t like VB’s decision to use the function name as the name of the return variable (why not Result, like in Pascal?) because this makes it inconsistent when the function returns an array:

Function Foo() As Integer()
    Foo = New Integer(2) { }
    Dim a = Foo(1) ''// Recursive call or access to return value element?
End Function

Of course that’s a recursive call (otherwise those wouldn’t be possible any longer). But I’m very annoyed by such inconsistencies so I don’t use the syntax.

On the other hand, there’s the advantage of a standardized name for the return value holder, and that’s definitely an advantage over the Return method.

Either way, VB generates the same code.


You could use reflector to check out out, but, in all honesty, whatever performance penalty there might be for something like this would fall squarely under the heading of "Premature optimization" .

From a syntactic perspective, the {Return "a value"} syntax tends to encourage multiple exit points from the method, which is often seen as a bad practice. But if the method is small, then I don't see that code readability would suffer from it.

OTOH, the {var = value; Return Var} syntax tends to promote a single exit point at the end of the function.


The execution difference is essential nil, so it would depend on which is easier to understand and maintain. I personally assign a variable to the function name before an exit or use the return statement, rather than using the function name as a variable throughout the function. It seems a little odd or ambiguous to me if I use the function name as a variable throughout the function.

If I remember right, return() was added as the return statement to a function between VB6 and VB.Net, probably to make it more like other languages. This would explain why there are the two ways to do the same thing.


As mentioned in this answer and in my comments to this answer, one feature of the function name as return variable is that it can be accessed (and changed) in a Finally after a Return has been used.

0

精彩评论

暂无评论...
验证码 换一张
取 消