Best vb.net questions in October 2011

What is the purpose of a stack? Why do we need it? (MSIL)

86 votes

So I am learning MSIL right now to learn to debug my C# .net applications.

I've always wondered: what is the purpose of the stack?

Just to put my question in context:
Why is there a transfer from memory to stack or "loading?" On the other hand, why is there a transfer from stack to memory or "storing"? Why not just have them all placed in the memory? (reflective question)

  • is it because it's faster?
  • is it because it's RAM based?
  • for efficiency?

I'm trying to grasp this to help me understand IL codes much more deeply.

Thanks for the help.

I've always wondered: what is the purpose of the stack?

I assume you mean the evaluation stack of the MSIL language, and not the actual per-thread stack at runtime.

Why is there a transfer from memory to stack or "loading?" On the other hand, why is there a transfer from stack to memory or "storing"? Why not just have them all placed in the memory?

MSIL is a "virtual machine" language. Compilers like the C# compiler generate IL, and then at runtime another compiler called the JIT (Just In Time) compiler turns the IL into actual machine code that can execute.

So first lets answer the question "why have MSIL at all?" Why not just have the C# compiler write out machine code?

Because it is cheaper to do it this way. Suppose we didn't do it that way; suppose each language has to have its own machine code generator. You have twenty different languages: C#, JScript .NET, Visual Basic, Iron Python, F#... And suppose you have ten different processors. How many code generators do you have to write? 20 x 10 = 200 code generators. That's a lot of work. Now suppose you want to add a new processor. You have to write the code generator for it twenty times, one for each language.

Furthermore, it is difficult and dangerous work. Writing efficient code generators for chips that you are not an expert on is a hard job! Compiler designers are experts on the semantic analysis of their language, not on efficient register allocation of new chip sets.

Now suppose we do it the IL way. How many IL generators do you have to write? One per language. How many jit compilers do you have to write? One per processor. Total: 20 + 10 = 30 code generators. Moreover, the language-to-IL generator is easy to write because IL is a simple language, and the IL-to-machine-code generator is also easy to write because IL is a simple language. We get rid of all of the intricacies of C# and VB and whatnot and "lower" everything to a simple language that is easy to write a jitter for.

Having an intermediate language lowers the cost of producing a new language compiler dramatically. It also lowers the cost of supporting a new chip dramatically. You want to support a new chip, you find some experts on that chip and have them write an IL jitter and you're done; you then support all those languages on your chip.

OK, so we've established why we have MSIL; because having an intermediate language lowers costs. Why then is the language a "stack machine"?

Because stack machines are conceptually very simple for language compiler writers to deal with. Stacks are a simple, easily understood mechanism for describing computations. Stack machines are also conceptually very easy for jit compiler writers to deal with. Using a stack is a simplifying abstraction, and therefore again, it lowers our costs.

You ask "why have a stack at all?" Why not just do everything directly out of memory? Well, let's think about that. Suppose you want to generate IL code for:

int x = A() + B() + C() + 10;

Suppose we have the convention that "add", "call", "store" and so on always take their arguments off the stack and put their result (if there is one) on the stack. To generate IL code for this C# we just say something like:

load the address of x // stack now contains address of x
call A()              // stack contains address of x and result of A()
call B()              // addr of x, result of A(), result of B()
add                   // addr of x, result of A() + B()
call C()              // addr of x, result of A() + B(), result of C()
add                   // addr of x, result of A() + B() + C()
load 10               // addr of x, result of A() + B() + C(), 10
add                   // addr of x, result of A() + B() + C() + 10
store in address      // result is now stored in x, stack is empty.

Now suppose we did it without a stack. We'll do it your way, where every opcode takes the addresses of its operands and the address to which it stores its result:

allocate temporary store T1 for result of A()
call A() with address of T1
allocate temporary store T2 for result of B()
call B() with address of T2
allocate temporary store T3 for result of first addition
add contents of T1 to T2, then store the result into address of T3
allocate temporary store T4 for result of C()
call C() with address of T4
allocate temporary store T5 for result of second addition
...

you see how this goes? Our code is getting huge because we have to explicitly allocate all the temporary storage that would normally by convention just go on the stack. Worse, our opcodes themselves are all getting enormous because they all now have to take as an argument the address that they're going to write their result into, and the address of each operand. An "add" instruction that knows that it is going to take two things off the stack and put one thing on can be a single byte. An add instruction that takes two operand addresses and a result address is going to be enormous.

We use stack-based opcodes because stacks solve the common problem. Namely: I want to allocate some temporary storage, use it very soon and then get rid of it quickly when I'm done. By making the assumption that we have a stack at our disposal we can make the opcodes very small and the code very terse.

UPDATE: Some additional thoughts

Incidentally, this idea of drastically lowering costs by (1) specifing a virtual machine, (2) writing compilers that target the VM language, and (3) writing implementations of the VM on a variety of hardware, is not a new idea at all. It did not originate with MSIL, LLVM, Java bytecode, or any other modern infrastructures. The earliest implementation of this strategy I'm aware of is the pcode machine from 1966.

The first I personally heard of this concept was when I learned how the Infocom implementors managed to get Zork running on so many different machines so well. They specified a virtual machine called the Z-machine and then made Z-machine emulators for all the hardware they wanted to run their games on. This had the added enormous benefit that they could implement virtual memory management on primitive 8-bit systems; a game could be larger than would fit into memory because they could just page the code in from disk when they needed it and discard it when they needed to load new code.

Why won't this seemingly correct .NET code compile?

23 votes

I'm asking in case I'm missing something obvious, but I think I may have stumbled upon a bug in .NET's compiler.

I have two projects in a .NET solution, one visual basic, one C#.

C# code, consisting of three overloaded static methods with default values:

public static class Class1
{

    public static void TestFunc(int val1, int val2 = 0)
    {
    }

    public static void TestFunc(int val1 = 0)
    {
    }

    public static void TestFunc(string val1, int val2 = 0)
    { 
    }
}

Visual basic code, calling one of the overloaded methods:

Option Explicit On
Option Strict On
Imports ClassLibrary1

Module Module1
    Sub Main()
        Dim x As Integer
        Class1.TestFunc(x, 0)
    End Sub
End Module

Compiling this code will fail, saying:

'TestFunc' is ambiguous because multiple kinds of members with this name exist in class 'ClassLibrary1.Class1'.

Why would it see this method as ambiguous? There is only one Class1.TestFunc with an (int, int) signature. Is this a bug, or am I missing something?

If you try to compile this in VB.NET you'll get

Sub TestFunc(ByVal val1 As Integer, Optional ByVal val2 As Integer = 0)

End Sub

Sub TestFunc(Optional ByVal val1 As Integer = 0)

End Sub

you'll get Public Sub TestFunc(val1 As Integer, [val2 As Integer = 0])' and 'Public Sub TestFunc([val1 As Integer = 0])' cannot overload each other because they differ only by optional parameters.

so I'll say that VB.NET is more limited than C# in optional parameters overload.

Why do C# and VB.NET implicitly marshal char* differently?

8 votes

So I have a function, written in C++, that looks like this...

extern "C" __declspec(dllexport) int __stdcall SomeFunction(char *theData)
{
    // stuff
}

... and I'm using it in my current project (written in C#). There are other projects that use this function written in VB, looking like this:

Public Declare Function SomeFunction Lib "MyDLL.dll" _
    Alias "_SomeFunction@4" (ByVal theData As String) As Integer

So I tried writing an equivalent in C#, but found that using the string type didn't actually work for me - the string would come back with the same data I passed it in with. I tried using "ref string" instead to pass the string by reference and I got a memory access violation.

After doing some digging, I found that this was the correct implementation in C#:

[DllImport("MyDLL.dll", EntryPoint = "_SomeFunction@4")]
public static extern int SomeFunction(StringBuilder theData);

Now I know that VB.NET and C# are quite different, but I suppose I always assumed that strings were strings. If one language can marshal char* to String implicitly, why can't the other, requiring a different class altogether?

(edited the title for clarity)

Now I know that VB.NET and C# are quite different, but I suppose I always assumed that strings were strings

Strings are immutable in .net. Ask yourself why it is that ByVal passing of an immutable data type can result in the value changing. That doesn't happen for normal functions, just for Declare.

I'd guess it all has to do with maintaining some backwards compatibility with Declare statements from classic VB6 which were done this way. To my mind the black sheep here is the VB.net code rather than the C# code.

Is it possible in .Net to catch all unhandled exceptions from any method in a class before its passed up the call stack?

8 votes

Problem:

I would like to catch any exceptions from any method in a class so that I may record class specific data to the exception for logging before it is passed up the stack. I know that I can put a try-catch in every method of the class, but there are many methods and It seems there should be a more efficient way.

Example of what I am currently doing:

public class ClassA
{
    private int x;
    private int y;

    public void Method1()
    {
        try
        {
           //Some code
        }
        catch(Exception ex)
        {
            ex.Data.Add("x", x);
            ex.Data.Add("y", y);
            throw;
        }
    }

    public void Method2()
    {
        try
        {
            //Some code
        }
        catch (Exception ex)
        {
            ex.Data.Add("x", x);
            ex.Data.Add("y", y);
            throw;
        }
    }
}

Example of what I would like to do:

public class ClassB : IUnhandledErrorHandler
{
    private int x;
    private int y;

    public void Method1()
    {
        //Some code
    }

    public void Method2()
    {
        //Some code
    }

    void IUnhandledErrorHandler.OnError(Exception ex)
    {
        ex.Data.Add("x", x);
        ex.Data.Add("y", y);
        throw;
    }
}

public interface IUnhandledErrorHandler
{
    void OnError(Exception ex);
}

Note: This class is a service in a WCF project and implements a ServiceContract. I have tried adding an ErrorHandler to the service's ChannelDispatcher. However, when the error reaches the ErrorHandler it is already beyond the scope of the class where the error occurred, so I cannot access the class details.

Solution:

public class ClassC
{
    public ClassC()
    {
        AppDomain.CurrentDomain.FirstChanceException += OnError;
    }

    private int x;
    private int y;

    public void Method1()
    {
        //Some code
    }

    public void Method2()
    {
        //Some code
    }

    private void OnError(object sender, System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs e)
    {
        e.Exception.Data["x"] = x;
        e.Exception.Data["y"] = y;
    }
}

If you run on .NET 4, you might use the FirstChanceException event from the AppDomain.

Visual Studio 2010 - C# editor more cumbersome than VB.NET editor

5 votes

I traditionally work in VB.NET, but have been asked to code the latest project in C#.

This is fine as I can work in either language, having had to frequently translate C# code to VB in the past and I've no qualms about developing in either.

My issue is with the Visual Studio editor and how many of the tasks that have traditionally been automated for me while writing VB.NET code are missing when writing C# code, or involve a larger variety of key-presses.

For example, creating a new #region or function...

In VB.NET creating a region involves typing "#r", at which point intellisense kicks in and shows me "#Region". I press "space" and "#Region" is auto-completed, thus allowing me to type the region name, then click "Enter" and the closing "#End Region" is automagically added.

In C#, I type "#r"... and nada.. I have to either click "Ctrl + k + x" and select #region from the list of snippets to achieve the same effect.

Similarly when writing functions in VB.NET ... the autocomplete creates the structure in seconds, whereas C# involves having to manually add the brackets etc, adding precious seconds to the development process. (or perhaps there is another shortcut key combo)

These are just two examples, but there are many others where the short-cuts that the VB.NET editor provides make coding much faster than the C# editor. I'm pretty shocked actually as C# is so often lauded for being "better" than VB.NET.

Anyway rant over.

My question is, are there any plugins which allow autocomplete on the C# editor in the same way as provided to the VB.NET editor?

Resharper.........................................................................

What files/folders must be added to source control?

4 votes

I need to know what files and folders must definitely be added to source control, and what files/folders can be left out.

I know I can leave out bin/ and obj/, along with the .suo file since it's user-specific, but what about the rest of the tree?

FWIW, here's a one form + one module project:

Directory of C:\Projects\MyApp\WindowsApplication1
03/10/2011  15:04             3.040 Form1.Designer.vb
03/10/2011  15:04             5.814 Form1.resx
03/10/2011  15:08             2.903 Form1.vb
03/10/2011  13:40               194 Module1.vb
03/10/2011  13:36    <DIR>          bin
03/10/2011  13:36    <DIR>          My Project
03/10/2011  13:36    <DIR>          obj
03/10/2011  13:36               934 WindowsApplication1.sln
03/10/2011  13:36             5.678 WindowsApplication1.vbproj
03/10/2011  13:36                74 WindowsApplication1.vbproj.user

Directory of C:\Projects\MyApp\WindowsApplication1\My Project
03/10/2011  02:51             1.522 Application.Designer.vb
03/10/2011  02:51               510 Application.myapp
03/10/2011  02:51             1.199 AssemblyInfo.vb
03/10/2011  02:51             2.807 Resources.Designer.vb
30/07/2008  06:54             5.612 Resources.resx
03/10/2011  02:51             3.058 Settings.Designer.vb
30/07/2008  06:54               279 Settings.settings
               7 File(s)         14.987 bytes

Thank you.


Can we safely ignore those folders? bin/, obj/, and My Project/.

What about WindowsApplication1.sln and WindowsApplication1.vbproj.user?

Leave out all these (credit, also documentation).

  • *.bin
  • *.obj
  • *.exe
  • *.dll
  • *.pch
  • *.user
  • *.suo
  • *.tlb
  • TestResults (VSTS unit test directory)

Alternatively, find a visual studio plug-in for your source control system (e.g. AnkhSVN for SVN) and it will do it automatically.

Cross thread operation not valid

4 votes

im trying to access a rich textbox on another form im using the following code to do so:

Private Delegate Sub StringDelegateChat(text As String, window As ChatWindow)
    Private Sub AppendTextChatWindows(text As String, window As ChatWindow)
        Try              
            If window.RichTextBox1.InvokeRequired Then
                window.Invoke(New StringDelegateChat(AddressOf AppendTextChatWindows), text, window)
            Else
                window.RichTextBox1.AppendText(text)
                window.RichTextBox1.SelectionStart = window.RichTextBox1.Text.Length
                window.RichTextBox1.ScrollToCaret()
            End If
        Catch ex As Exception
            MessageBox.Show(ex.ToString)
        End Try
    End Sub

but i get the cross thread operation not valid error, i think it does this because it misses out the window.invoke part of the if statement. i also tried replacing theIf window.RichTextBox1.InvokeRequired Then to If InvokeRequired Then but it gets caught in a continues loop and a stack overflow error is thrown.

Thanks Houlahan

I believe, on line 5, window.Invoke should be changed to window.RichTextBox1.Invoke.

Private Delegate Sub StringDelegateChat(text As String, window As ChatWindow)
Private Sub AppendTextChatWindows(text As String, window As ChatWindow)
    Try
        If window.RichTextBox1.InvokeRequired Then
            window.RichTextBox1.Invoke(New StringDelegateChat(AddressOf AppendTextChatWindows), text, window)
        Else
            window.RichTextBox1.AppendText(text)
            window.RichTextBox1.SelectionStart = window.RichTextBox1.Text.Length
            window.RichTextBox1.ScrollToCaret()
        End If
    Catch ex As Exception
        MessageBox.Show(ex.ToString)
    End Try
End Sub

In ASP, C#, and VB.Net how to retrieve current line number

4 votes

Does ASP, C#, VB.NET have a way to retrieve what line its on in code as its processing commands?

Example

1 <%
2 response.write("Your on line " & retreiveCurrentLineNumber)
3 %>

Output: Your on line 2

You can do this:

var line = new StackFrame(0, true).GetFileLineNumber();

Note there are several caveats to this.

  1. You will need to make sure the source file and PDB are reachable.
  2. This will get you the current line of the method you are in, not exactly where you are.
  3. The Jit may perform optimizations that result in incorrect information, such as a method being inlined.

For VB.NET it's the same thing:

Dim line As Integer = New StackFrame(0, True).GetFileLineNumber()

As far as Classic ASP goes - I don't believe this is possible.

Does the JIT compiler optimize (inline) unnecessary variable declarations?

4 votes

I've read several articles and questions/answers that conclude the best practice is to let the JIT compiler do all the optimization for inline function calls. Makes sense.

What about inline variable declarations? Does the compiler optimize these as well?

That is, will this:

        Dim h = (a + b + c) / 2       'Half-Perimeter

        If maxEdgeLength / (Math.Sqrt(h * (h - a) * (h - b) * (h - c)) / h) <= MaximumTriangleAspectRatio Then
           'Do stuff here.
        End If

Have better performance than this:

        Dim perimeter = a + b + c   'Perimeter
        Dim h = perimeter / 2       'Half-Perimeter

        Dim area = Math.Sqrt(h * (h - a) * (h - b) * (h - c)) 'Heron's forumula.
        Dim inradius = area / h
        Dim aspectRatio = maxEdgeLength / inradius

        If aspectRatio <= MaximumTriangleAspectRatio Then
            'Do stuff here.
        End If

Of course I prefer the latter because it's easier to read and debug, but I can't afford the performance degradation if it exists.

Note: I have already identified this code as a bottleneck -- No need for retorts about premature optimization. :-)

Temporary variables having names or not is a non-issue.

But you can optimize that inequality significantly.

Your code was:

If maxEdgeLength / (Math.Sqrt(h * (h - a) * (h - b) * (h - c)) / h) <= MaximumTriangleAspectRatio Then

Multiply both sides by the square root, eliminating division (inequality is preserved, because square root cannot return a negative number):

If maxEdgeLength <= (Math.Sqrt(h * (h - a) * (h - b) * (h - c)) / h) * MaximumTriangleAspectRatio Then

Now, square both sides to eliminate that expensive square root:

If maxEdgeLength * maxEdgeLength <= h * (h - a) * (h - b) * (h - c) / h / h * MaximumTriangleAspectRatio * MaximumTriangleAspectRatio Then

Cancel, and multiply by h.

If maxEdgeLength * maxEdgeLength * h <= (h - a) * (h - b) * (h - c) * MaximumTriangleAspectRatio * MaximumTriangleAspectRatio Then

This will be a lot faster. If this calculation is repeated, consider caching the results of part of this expression for even more improvement.

Use comments to explain the formula. Getting rid of a Math.Sqrt call in a bottleneck function is worth writing the expression in a less-than-simple format.

Classes and Files VB .Net

3 votes

I have close to 150 reference tables and I am working on the service which would get the reference lists. I am trying to write a code generator and would like to know if there are any performance related problems if I have multiple classes in one file. I know that it would be difficult to maintain one huge file. But I am more concerned over performance than maintenance.

Any suggestions are most welcome.

Thanks in advance.

Regards,

Raja

It'll make no difference to the compiled code. I do this all the time in Protocol Buffers with the generated code - admittedly that's C#, but it's the same principle.

It may well make Visual Studio slow if you ever open that generated code file, e.g. for debugging, but that's a different matter. (I believe Visual Studio on its own isn't too bad, but I seem to remember that Resharper slows down with big files. Apologies to Jetbrains if I'm misremembering this!)

From the point of view of making the generated code easier to include in project files etc, it's handy to have just a few large files rather than lots of small ones, so it sounds to me like you're doing the right thing.

Center drawn text

3 votes

I'm drawing text in VB.net by using:

gfx.DrawString(_bText, New Font("Tahoma", 5), Brushes.Black, New Point(25, 5))

where gfx is a graphics object using my control. The x point is correct but I need the y to be the center of the current contol (vertically). Is there an easy way to do this?

TextRenderer has a VerticalCenter flag:

Dim r As New Rectangle(25, 0, myControl.ClientSize.Width - 25, _
                              myControl.ClientSize.Height)

Using myFont As New Font("Tahoma", 5)
  TextRenderer.DrawText(gfx, _bText, myFont, r, _
                        Color.Black, Color.Empty, _
                        TextFormatFlags.VerticalCenter)
End Using

Converting C# to VB.net is not working

3 votes

I have translated some code from C# to VB.net for the purpose of getting Folder Browser functionality. The link to the code is here.....

http://www.codeproject.com/KB/aspnet/DirectoryBrowsing.aspx

My issue is that I have not been able to correcly translate these two lines of code to VB.net.

TreeView1.TreeNodeExpanded +=new TreeNodeEventHandler(TreeView1_TreeNodeExpanded);
TreeView1.SelectedNodeChanged += new EventHandler(TreeView1_SelectedNodeChanged);

Every translator I have used has simply dropped the semicolon from the end of each line. But the editor still does not like them.

Could some please helps with this as it seems this effects the refersh of the selected folder in the tree view conrol.

enter image description here

I don't get to see the C drive folder unless I type the path in the text box, and the folder will still not expand.

thank you,

Use this:

AddHandler TreeView1.TreeNodeExpanded, AddressOf TreeView1_TreeNodeExpanded
AddHandler TreeView1.SelectedNodeChanged, AddressOf TreeView1_SelectedNodeChanged

Edit:

A different way to do this would be to apply it at the method level:

Protected Sub TreeView1_TreeNodeExpanded(ByVal sender as Object, ByVal e as TreeNodeEventArgs) Handles TreeView1.TreeNodeExpanded

    ' Some code

End Sub

Protected Sub TreeView1_SelectedNodeChanged(ByVal sender as Object, ByVal e as EventArgs) Handles TreeView1.SelectedNodeChanged

    ' Some code

End Sub

You should run this in debug to find out what exactly is going on. I find a lot of times when events of this nature are run in asp.net, you have a conflicting event that "resets" the controls you are attempting to change.