Vb. NET is how to do (Moving edition)

Source: Internet
Author: User
Tags filter bind exit error code error handling exception handling implement variables

VB.net can implement many functions that C # cannot do, such as when statement, optional parameter, local static variable, object instance access static method, handles binding event, on error handling exception, Object direct late binding, and so on. VB and C # belong to the same. NET language, compiled with the same CIL, but why VB support a lot of interesting features. Let's explore it together.

(i) Local static variables

VB supports declaring local variables with the static keyword so that the value of the variable can be persisted at the end of the process:

Public Sub Test1 ()

Static I as Integer

i + 1 ' implements a procedure call counter

End Sub

We have implemented a simple process counter. Each time you call test, the counter's value increases by 1. There are many situations where we want to keep the values of the variables. The static of C # cannot be used within the process. So to implement the process counter, we have to declare a class-level variable. This is obviously not as good as VB. Because it is not possible to prevent other procedures from modifying counter variables. This is the same thing as the object encapsulation, which should have been a local variable of a method, and now I am forced to separate it out, obviously a bad design. So how does VB generate local static variables? By returning the code back to the assembly, we can clearly see that I was not a local variable in VB-generated CIL, but rather as a field of the class:

. field Private specialname int32 $STATIC $test1$2001$i

In other words, I was renamed as a class field, but was dubbed SpecialName. Attempting to access $static$test1$2001$i in code is not possible because it is not a valid identifier. But in IL, the code that adds this variable to one is exactly the same as the generic class field, and is loaded by ldfld. I think this method is very clever, the static variable into the life cycle of the same class field, but also by the compiler to control access to the permissions, let it become a local variable. It also explains why VB uses two different keywords to declare static variables--static and shared.

Because the essence of the local static variable is the field of the class, it is different from the real local variable. For example, in multi-threaded conditions, access to local static variables is the same as the Access field.

(ii) MyClass keywords

VB.net supports a very interesting feature--myclass. Most people using MyClass may be limited to invoking other constructors in this class. In fact, MyClass can produce some very unique usage. MyClass is always invoked as a member of a class that cannot be rewritten, that is, when a class's method is overridden, it can still get its own version with MyClass. The following example is very similar to the example given in VB Help

Public Class Myclassbase
Protected Overridable Sub Greeting ()
Console.WriteLine ("Hello form Base")
End Sub

Public Sub Useme ()
Me.greeting ()
End Sub

Public Sub Usemyclass ()
Myclass.greeting ()
End Sub
End Class

Public Class Myclasssub
Inherits Myclassbase

Protected Overrides Sub Greeting ()
Console.WriteLine ("Hello form Sub")
End Sub
End Class

We use a code to test:

Dim o as Myclassbase = New myclasssub ()

O.useme ()
O.usemyclass ()

The result is that Useme executes the version of the subclass, and Usemyclass still executes the version of the base class itself, although this is a virtual method. With its IL, you can see its simple principle of implementation:

The call instruction for me is callvirt

Il_0001:callvirt instance void App1.myclassbase::greeting ()

and MyClass called call.

Il_0001:call instance void App1.myclassbase::greeting ()

Strangely, such a simple function, I can not be implemented in C #, C # does not allow me to call a virtual function in the form of non-virtual functions. C + + can access its own version of a function using the class Name:: Method Name, but C # 's class name can only be used to access static members. This is really a strange limitation of C #.

(iii) Handles and WithEvents

VB in addition to using C # as a way to deal with the event response, there are inherited from the VB5 unique event handling way--withevents.

I like to call this event handling as static event handling, when writing a method of responding to an event, you decide which event the method responds to, and C # binds the event in code. For example, here's the simplest example:

Public Class Handlerclass
Public WithEvents MyObj as EventClass


Private Sub myobj_myevent (ByVal sender as Object, ByVal e as System.EventArgs) Handles myobj.myevent
MsgBox ("Hello")
End Sub

Public Sub New ()
myobj = New EventClass
End Sub
End Class

The EventClass used in the code is this:

Public Class EventClass
Public Event MyEvent as EventHandler

Protected Overridable Sub onmyevent (ByVal e as EventArgs)
RaiseEvent MyEvent (Me, E)
End Sub

Public Sub Test ()
Onmyevent (New EventArgs)
End Sub
End Class

Let's review the code implicitly to write two methods--add_myevent (EventHandler) and Remove_myevent (EventHandler) to EventClass, In fact, any context that uses the event is invoked to bind the event and unbind the two methods. C # also allows you to write your own event binding/unbind code.

So how does WithEvents work? The vb.net compiler automatically compiles the

Public WithEvents MyObj as EventClass

Translated into the following process:

Private _myobj as EventClass

Public Property MyObj () as EventClass
Get
Return _myobj
End Get
Set (ByVal Value as EventClass)

If not (Me._myobj are nothing) Then
RemoveHandler _myobj.myevent, AddressOf myobj_myevent
End If

Me._myobj = Value

If Me._myobj is no Then Exit property

AddHandler _myobj.myevent, AddressOf myobj_myevent

End Set
End Property

Thus, when assigning a value to a WithEvents variable, this property is automatically triggered to bind the event. Most of the event responses we use are 1 to 1, a process that responds to an event, so this WithEvents static method is very useful, it can significantly enhance the readability of the code, but also make the event handling in vb.net very convenient, unlike C # That leaves the form designer to bind events manually.

But in the analysis of this IL, I also found vb.net in the translation of a small problem, that is, ldarg.0 appear too much, this is the frequent use of me or this performance, so we must pay attention in the coding process, in addition to the use of Me/this itself reference, Use its members do not bring me/this, such as Me.myInt = 1 change to MyInt = 1, such a small habit will bring you a lot of performance benefits.

(iv) Type conversion operators

In Visual Basic 2005, a new operator--trycast is added, which is equivalent to the as operator of C #. I always hope that VB has such an operator. VB's current type conversion operators are mainly CType and DirectCast. Their usage is almost the same. I compared the two operators in detail and came to the following conclusions:

1. When converting to a reference type, there is no difference between the two, which is to invoke the castclass instruction directly unless the type conversion operator CType is overloaded. The DirectCast operator is not overloaded.

2. When converting to a value type, CType invokes the type conversion function specified by VB (if any), such as converting a string to Int32, The VisualBasic.CompilerServices.IntegerType.FromString is invoked automatically, and Fromobject is invoked when object is converted to Int32. When other numeric types are converted to Int32, CType also invokes the conversion method of the type itself. The DirectCast operator is simple enough to simply disassemble the object into the desired type.

So when it comes to value types, CType does not directcast fast but can support more conversions. In C #, type conversions are (type) operators and as operators. The (type) operator works much like VB's DirectCast, and is also a direct unboxing or castclass, but if you encounter supported type conversions (such as long to int), the (type) operator also invokes the corresponding conversion method. However, conversions from string to int are not supported. C # Another operator as is more intelligent, it is only to determine whether the object's running instance can be converted to the target type, then you can omit the castclass instruction, directly to the known type of operation, and the compiler can also automatically optimize as, such as saving an object reference. So when you convert object to the desired type, as is the best choice.

Because as has many advantages, Visual Basic 2005 absorbs this feature and uses the TryCast operator to get the same effect as the AS, and the syntax is the same as DirectCast or CType.

(v) Interface implementation

VB.net's implementation of the interface syntax is the VB5 invention of the implements, the implementation of interface syntax in today's mainstream language is unique. For example, I have two interfaces:

Interface Interface1
Sub Test ()
End Interface

Interface Interface2
Sub Test ()
End Interface

The two interfaces have exactly the same member test. What if I need to implement two interfaces with a class at the same time? First think about it, if it is java,jscrip.net such a language can only use a test function to implement the two interface test members. If two test is only accidental duplicate name, its content must be implemented separately, so some solution interface duplicate design appeared ... In VB, the unique implements statement allows you to think how to implement the interface how to implement, such as the following class implementation with two names are not the same way to implement two interfaces.

Public Class Implementation
Implements Interface1, Interface2

Public Sub Hello () Implements interface1.test

End Sub

Private Sub Hi () Implements interface2.test

End Sub
End Class

In other words, VB allows the function of any name to implement the members of the interface, and the accessor can be arbitrary, such as to use public or private can.

C # provides an explicit implementation (explicit implementation) syntax for dealing with duplicate members, which implements the syntax of the two interfaces

public class Class1:interface1, Interface2
{
Public Class1 ()
{
}
void Interface1.test ()
{
}

void Interface2.test ()
{
}

}

Note here, C # can only use the interface name. Name of the member name to name the implementation method, and the accessor can only be private and cannot expose a method that is explicitly implemented.

After examining the IL, I found that. NET supports both implicit and explicit implementations. The implicit implementation is simply to put a method in the class with the same name as the interface member method--This kind of VB does not support. An explicit implementation is added to the descriptive information of the method:

. Override Testapp.interface1::test

Whether it is the explicit implementation of C # or VB Implements statements are such a principle. Other words. NET provides the function of exchanging name to implement interface member, but only VB has given this freedom to the user, but other languages still adopt the classic grammar.

(vi) Default properties and property parameters

In the original VB6, there was a peculiar function-the default attribute. In VB6, the name of an object can directly represent the default property of that object. For example, the default property of a TextBox is text, so the following code

Text1.Text = "Hello"

can be simplified to

Text1 = "Hello"

This simplification brings a lot of trouble to VB, assignment operation requires two keywords--let and set, the result attribute process also need let and set two kinds. And this feature can still work when it is late bound. To vb.net, this feature is greatly limited, and now only attributes with parameters can be used as default properties. Such as

List1.item (0) = "Hello"

can be simplified to

List1 (0) = "Hello"

This syntax makes an object with a default property look like an array. So how does VB judge whether a property is a default property? Look at the following code

public Class proptest
    Public Property P1 (ByVal index as Integer) as String
&nbs p;       get

        end Get
         Set (ByVal Value as String)

        End Set
    End Property

    Default Public Property P2 (ByVal index as Integer) As String
        get

        End Get
        Set (ByVal Value as String)

         End Set
    End Property
End Class

The P1 and P2 two properties are essentially identical, and the only difference is that P2 has a default modifier. After disassembly of this class, two attributes are found to be identical, without any difference. However, the Proptest class is added with a custom meta attribute System.Reflection.DefaultMemberAttribute. The member specified by this meta attribute is the default type used by InvokeMember, which means that the default property can also be used for late binding. But I experimented. Adding the DefaultMember meta attribute manually to a type does not achieve the ability to make a property default. It seems that this function is a VB "grammatical sweetness." However, VB or C # compiler for other generated classes of the default properties should only be judged by defaultmemberattribute, so I will be a VB class only DefaultMemberAttribute Specify a default method, do not use default, Then compile it for C #, and sure enough, C # will recognize it as an indexer (indexer)!

Now that we've talked about the C # Indexer, we'll take a look at the differences between VB and C # properties. The result of the experiment just now is that the default property of VB is the indexer in C #. However, VB can still use the syntax of the property to access the default properties, and C # can only use the syntax of the array to access the indexer. More specifically, VB can create a property that is not the default but the attributes with parameters, such as the P1 in the example above, and C # does not support attributes with parameters, if the VB written, with the parameter attributes of the class to C #, C # will prompt the "property is not supported by this language, please use GET_XXX and set_ Syntax access for XXX. " That is, a property with parameters is a feature of the CLR, but not CLS-compliant (Common language specification), and thus a cross-language barrier occurs. This also reinforces our understanding of the CLS--if you want your code to work across languages, be sure to be aware of CLS-compliant.

(vii) Optional parameters and pass by name

VB supports the feature "optional parameters" starting from 4.0. That is, some of the parameters of a function or subroutine are optional and can be invoked without input. In fact, VB from the beginning of 1.0 there are some functions with optional parameters, but only to 4.0 to allow users to develop such a process themselves. In VB4, an optional parameter can have no default value, and in vb.net, if you use an optional parameter, you must have a default value. Such as

Public Sub testoptional (Optional i as Integer = 1)

End Sub

When invoked, it can be written either as testoptional (2) or as a testoptional (), and this condition parameter I automatically equals 1. If the procedure has more than one optional parameter, VB also provides a way to simplify operations-passing parameters by name. such as process

Public Sub testoptional (Optional i as Int32 = 1, Optional j as Int32 = 1, Optional k as Int32 = 1)

End Sub

If you want to specify K only, let I and J use the default values, you can use the by name pass, as follows

Testoptional (k: = 2)

And this way is not limited by the order of parameter tables

Testoptional (k: = 2, I: = 3, J: = 5)

These are indeed quite handy features, and C # does not support both of these features. Let's see how it is implemented at the IL level. The first method described above is defined in the IL as

. method public instance void Testoptional ([opt] int32 i) CIL managed
{
. param [1] = Int32 (0x00000001)
. maxstack 8

Visible, the parameter is added with the [opt] modifier, and. PARAM specifies the default value for the parameter. This is only VB can recognize the content, C # will skip them. When a call is made, VB automatically reads the default value of the. param part and passes it explicitly to the procedure if it finds that the parameter is omitted. This part is entirely handled by the compiler and has no performance penalty, and is exactly the same as passing all parameters manually. As for the transfer by name, VB will automatically adjust the order of parameters, the results and the traditional way of transmission is not any different. This means that we can safely use this convenience. And with optional parameters of the process to get C #, the most becomes an optional parameter, also does not cause any other trouble.

PS. Many COM components use the default parameters, and some procedures have a very long list of parameters, in VB can easily handle them, and in C # often allow developers to pass the parameters to vomit blood.

(eight) On Error statement and when statement

This is a discussion of exception handling statements. Vb. NET recommended to use Try ... End Try block for structured exception handling, but in order to ensure compatibility, it also borrows the On Error statement from the previous version of Basic. In fact, on error is not the advantages of VB, because the use of it will destroy the structure of the program, so that with exception handling procedures difficult to understand and debug. But I have always been amazed at how VB engineers implement it, because on error allows abnormal jumps to change very flexibly, not as limited as try. First look at how the try is implemented:

Public Function F1 () as Integer
Try
Dim N as Integer = 2 \ n
Catch ex as Exception
MsgBox (ex. Message)
End Try
End Function

This is the simplest exception handler, through the reflector disassembly (if you use ILDASM, do not choose "expand Try-catch"), you can find that the whole process is translated into 19 instructions. Pay attention to this sentence:

. Try l_0000 to l_0006 catch Exception l_0006 to l_0022

This is the typical try block, specifying the exception to catch directly at the catch, and then specifying the location of the catch area, very clear. Also pay attention to these two sentences:

L_0007:call Projectdata.setprojecterror

L_001b:call Projectdata.clearprojecterror

As you can see, these two sentences are at the beginning and end of the catch block. In both of these processes I found that it was logging an exception for the Err object. It seems to use err is also a grammatical sweetness, the performance of the pain, added these two lines (fortunately not too complicated).

Next I wrote a function similar to this one, with an on statement to handle the exception:

Public Function F2 () as Integer
On Error GoTo Catchblock
Dim N as Integer = 2 \ n
Exit Function
Catchblock:

MsgBox (Err.Description)

End Function

This is not more complicated than the previous process, but after disassembly, its IL code unexpectedly has 47 instructions, just 19! The main change is the try part, now it's like this:

. Try l_0000 to l_0022 filter l_0022 l_0036 to l_0060

Notice that the catch is gone and the filter appears. I have never seen filter in the IL generated by C #. I queried the Meta data section of the document, filter may be able to do some filtering, meet certain conditions before entering the processing of the exception block, in this case, the l_0022 instruction began is the filter, it is:

L_0022:isinst Exception
L_0027:BRFALSE.S l_0033
L_0029:ldloc.s V_4
L_002B:BRFALSE.S l_0033
L_002d:ldloc.3
L_002E:BRTRUE.S l_0033
l_0030:ldc.i4.1
L_0031:BR.S l_0034
l_0033:ldc.i4.0
L_0034:endfilter

Endfilter is the beginning of the exception handling part of the code. and L0030 before the code is the filter part of the decision, V_4 and V_3 is VB to add their own to save the error code variables. In the entire disassembly, I found that the code designed to handle the anomaly is actually in the try block in IL, which means that the structure of the program is not a regular try...catch block, resulting in an exception to the statement and handling the exception of the statement, and the real deal with the exception of the instructions is a lot of cumbersome to procrastinate jump statements.

Let's look at the third example I've written:

Public Function F3 () as Integer
On Error Resume Next
Dim N as Integer = 2 \ n
End Function

This value has 2 lines of the process using the VB powerful syntax killer--on Error Resume Next, it will ignore all exceptions, so that the code immediately generated the exception of the statement to continue, guess how many of the function generated IL instructions? The answer is 50! Longer than the normal on error. I don't say much about it, just like the previous on statement. But the number 50 seems to remind you not to use the On error to handle exceptions in your program, which is unacceptable.

The last example is the vb.net when statement, which enables filtering of the catch part:

Public Function F1 () as Integer
Dim N as Integer = 0
Try
Dim m as Integer = 2 \ n
Catch ex as Exception when n = 0
MsgBox (ex. Message)
End Try
End Function

The When statement inside the decision to the variable n, only when n = 0 to enter the processing section. Hear "filter" two words, we have guessed, it is to use try...filter to achieve. That's right. Here the filter is mainly to whether ex is exception type, n is equal to zero, when the filter succeeds, it will be transferred to the exception processing segment for processing. VB generated by the code than on the error statement more rules, the structure is quite clear.

This time we also use the On Error statement and the When statement to understand the try filter structure, which is C # can not be generated, so I found that it can not be the common anti-compiler decompile (because the compiler's creator only know C #, hehe). And with the On error after the program structure becomes extremely chaotic, this in the negative effect, is it possible to disguise the role of protecting our code?

(ix) Instance access to shared members

We all know that static members in VB is called shared members, although just accepted a bit awkward, but "shared members" is indeed a veritable:

Public Class Class1
Public Shared I as Integer
' Other none-shared members
End Class

Not only as in C #, you can access shared member I with CLASS1.I, but you can also use instance variables to visit:

Dim C1 as New Class1
c1.i = 100

It's like I'm a member of the C1! Of course there is only one I, any instance to modify the value of I will cause all I values to change (because there is actually only one). Even me and MyClass can access shared members.

ME.I = 100
MYCLASS.I = 100

This is not possible in C #, and a pure C # Programmer will find this code unthinkable. To reveal how it works, we can do the following experiments:

Dim C1 as Class1
c1.i = 100

Note that the C1 here is nothing!, and even a variable of nothing can access the shared member without error. And then we'll experiment with more extreme situations:

Dim o as Object = New Class1
O.I = 100

Results-Failed to access shared members through late-bound. Now the result is obvious, only when VB explicitly understand the object type, you can use the instance to access the shared members, VB will automatically judge the type, and then all the statements to the shared members are rewritten into

class1.i = 100

Such a syntax. Delphi also supports this interesting feature, and Levi says in Inside VCL that Delphi.NET is one of the extensions to. Net.



Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.