• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 489
  • Last Modified:

Inherit question in vb.net?

Hi,

Does this method look OK?

Public MustInherit Class ClassA
    Protected myValue As Double

    Public ReadOnly Property MyValue() As Double
        Get
            MyValue =myValue
        End Get
    End Property

    Protected Function CalcValue(ByVal Arg1 As Double) As Boolean
     
        Try
            myValue = arg1*10

            CalcValue1 = True
       Catch ex As Exception
            CalcValue1 = False
         
        End Try
    End Function
End Class
Public Class ClassB
    Public Function CalcValue(ByVal Arg1 As Double, ByRef myValue As Double) As Boolean
   
        Try
             myValue = arg1*10

            CalcValue1 = True
       Catch ex As Exception
            CalcValue1 = False
           
        End Try
    End Function
End Class


ClassA1CalcValue(arg1) and ClassB.calcValue(arg1,myValue)

I have the following code and trying to understand what's the difference between two methods calls.
One is a baseclass and other is a subclass.
Why do I need to pass the myValue in the subclass of method by ByRef?
0
dkim18
Asked:
dkim18
  • 5
  • 5
  • 3
  • +1
3 Solutions
 
AndyAinscowCommented:
ByVal - that passes just the value into a NEW variable local to the method, changes made to it are thrown away after the method finishes.

ByRef - that passes the variable itself into the method.  Any changes made are still there after the method finishes.



crudely:

foo(byval x, byref y)
x = 27
y = 27
end foo

...............
x = 3
y = 4
foo(x, y)

now x = 3 and y = 27
0
 
Jacques Bourgeois (James Burger)PresidentCommented:
There is no inheritance between the 2 classes.

If there was inheritance, the declaration for ClassB would be:

Public Class ClassB
     Inherits Class A

Since ClassB does not inherits from ClassA, it has no obligation of declaring the method with the same way as it is in ClassA.
0
 
dkim18Author Commented:
Sorry I missed that.

ClassB gets inherited from ClassA.
Public Class ClassB
     Inherits Class A
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
Jacques Bourgeois (James Burger)PresidentCommented:
A lot of bad things in that code.

First of all, it cannot compile, at least not in VB. In ClassA, you have a variable and a property that have the same name. VB is not case sensitive as some other languages are. For the compiler, you have 2 elements with the same name, and that would not compile.

Then, the variable associated with the property should be Private. Because it is not, it enables a bypass of the ReadOnly in the method.

Second, that function (both functions in fact) is very badly designed. Basically, this a a function that performs a calculation, so it should normally return the value of the calculation, and throw an Exception if it catch one.

Instead, the programmer used an old technique that is carried from the C language. A few programmers use it in VB. Instead of returning a value, the function returns an error code. The result of the value will be passed back to the caller in the second parameter. ByRef means that what is received by the function is not the value of the parameter, but a pointer, the address in memory of the variable that was passed. When MyValue is manipulated in the routine, it thus changes the value at that address. When the function return, the second parameter contains the result of the calculation.

This is not good programming nowadays. Simply returning True or False to indicate that there has been an error is useless. The programmer that uses the class has no idea of what the problem was and does not know how to correct that. Ideally, the function should look something like this in ClassB, so that it returns the result of the calculation, but pass back the exception if there was one (ClassA should also have its Function work in a similar way):

  Function CalcValue(ByVal Arg1 As Double) As Double
        Try
           return arg1*10
        Catch
            Throw        
        End Try
  End Function

As for the ByRef, you should ask the programmer. The only reason I see is that because the method is Protected in ClassA, users of ClassB cannot call it. And because the property is ReadOnly in ClassA, the code in ClassB cannot use it (I told you that the variable in ClassA should be Private). In fact, I wonder what is the use of ClassA. It defines something that can me used only internally in the class.

The programmer of ClassB saw that the way the combinations Protected Function / ReadOnly Property made that method useless and thus rewrite it. He followed the bad idea of returning the error as a Boolean, and since he had used the return value for that, he needed a way to return the result of the calculation. ByRef enables him to do that as explained before.

ClassA was poorly designed. ClassB tried to go over the problems, but is also poorly designed.
0
 
AndyAinscowCommented:
Before you go to much into redesigning the classes - did you understand the byref/byval details?
0
 
dkim18Author Commented:
THanks JamesBurger for your explanation.

You are right about above code.
It has a lot of bugs. I was trying to copy the code and rename some of variable names and made a few mistakes.
Thanks for pointing out.

Can I ask you a little more of returning the boolean as the sign of the error?
Some of the examples  I read use this kind of programming.
DoSomething(ByRef x as InputType, ByRef y as OutputType) as Boolean.

I have this application which does a lot of calculation and has over 50 calculation methods.
I am trying to come up with some kind of error code, (101 for error from method xxx, 102 for error from method xxy..etc)

I was going to include those in another error object. Maybe something like this
DoSomething(ByRef x as InputType, ByRef y as OutputType, ByRef z as ErrorType) as Boolean.

What I really want to do is, if error comes up, I want to capture it and tell users where and what happened.

I want the method to handle the error and not where the method was called.
0
 
AndyAinscowCommented:
A typical way is to return an integer value with the error.  Zero meaning all is OK, non zero is something went wrong - so just check for zero to check if successful.

eg.
long foo(.....)

....

long l = foo(x, y, z...)
if l <> 0 then
  'something went wrong, inspect the actual value in l
end if
0
 
Jacques Bourgeois (James Burger)PresidentCommented:
Returning an error code can be typical in other languages and environment, but not in .NET where it is rarely used.

How do you catch an error yourself? With a Try...Catch. So how do you think the user of your own classes expects to catch errors? With a Try...Catch also. So you should return an Exception, not a Boolean.

The thing could be more elaborated in a tightly build class, but what I have shown is the easiest way to do so:

    Catch
            Throw    

This sends back the exact error you trapped to the caller, who will retrieve it if he calls your method the following way:

Dim x As New ClassB
Try
     CalcValue(23.15, someVariable)
Catch ex As Exception
     'Here the caller can do anything he wants when there is an error
End Try

In the Catch, the caller can retrieve information from the ex variable, such as ex.Message. He will thus be able to know if the problem is that he sends a value that was to big for a double or is anything else. With a Boolean, how he knows is that there was an error, but no way to know why.

If you would rather go for an error code, don't. Still use an Exception, but put the code in the Message by sending the error the following way:

     Throw New Exception ("The error code is 101")

or maybe better, because the caller won't have to consult your documentation to know what error code 101 means:

     Throw New Exception ("Error while calling function CalcValue in ClassB")

Even better, hide the details of the exception that you trapped yourself in your own:

     Throw New Exception ("Error while calling function CalcValue", ex)

That way, the program that uses your class will have a clear information. And in debugging, the programmer who receives that Exception will be able to examine ex.InnerException to know what really happened in CalcValue.

This is the simplest way to go. Ideally, you should go further than this. The topic is discussed in the Visual Studio documentation. Look for "custom exceptions" in the Index of help.

And please, forget the tone of my previous message. It was late and by rereading it I find it quite harsh.

I would tell it otherwise this morning, and I would add the following. When you declare a variable, a property or a method, always have a reason for the modifiers. Always ask questions such as the following:

- Why do I declare the variable Protected?

- Why is the property ReadOnly?

- You are recoding basically the same function in ClassB that you have in ClassA. Why make it Protected in ClassA. Why not leave it Public so that ClassB inherits its functionnality. This is what inheritance is all about after all.

If you are adapting code that you have seen somewhere else, try to understand why the programmer did so. In object oriented programming, these modifiers have a lot more impact than the difference between ByRef and ByVal, believe me. If you do not know what they mean, go F1 on them. Do not go further unless you understand the impact they have over the way inheritance works.

And by the way, the need of ByRef variables is quite rare in .Net. Most of the time I see one, it is out of an old habit from older VB programmers because it was the default in VB6, or because there is something that the programmer does not know in the framework. Look at the 9000+ classes of the framework with their 30 or so methods each. You will find it difficult to find one that uses a ByRef parameter. ByRef parameters have their place in a few rare conditions, but they are dangerous, because they change the values of variables without the knowledge of the programmer who created those variables. There is almost always a better workaround for a ByRef variables. Microsoft removed the notion of pointer in .NET for good reasons. Using ByRef bring backs some of the old problems of pointers.
0
 
Mike TomlinsonMiddle School Assistant TeacherCommented:
"Returning an error code can be typical in other languages and environment, but not in .NET where it is rarely used."

Not sure about the "rare" part...

One of the most common uses of a return code (true/false) AND a byref/out parameter is the TryParse()/TryParseExacty() series.  This gets used ALL the time in .Net to validate input...

Int32.TryParse(): http://msdn.microsoft.com/en-us/library/f02979c7.aspx
DateTime.TryParse(): http://msdn.microsoft.com/en-us/library/ch92fbc1.aspx
etc... http://social.msdn.microsoft.com/Search/en-US?query=tryparse&ac=3

Most people I know would rather use a TryParse() method than wrap the equivalent in a Try/Catch block.
0
 
Jacques Bourgeois (James Burger)PresidentCommented:
"rare" does not mean that it does not happen in often used method. It means that it happens in very few methods. And when it does, it needs to be justified.

There is only one reason for TryParse not to work: you are trying to convert a value that does not fit in the specified type.

TryParse is used only for base types that everybody know after 2 days of working with the framework, so the reason should be obvious once you know the value that you were trying to convert. No need to add to the information that the conversion was impossible. It is also used only with types that are Structures, objects that are far simpler than others that are for the most part classes with many properties.

"Most people would rather use a TryParse() than wrap the equivalent in a Try/Catch"

But it is not because TryParse is easier to use. What is the difference, fundamentally, for the programmer work load, between:

Try
   x=CInt (y)
Catch ex As Exception
  'Handle the Exception
End Catch

... and ...

If
   Integer.TryParse (y,x)
Else
   'Handle the Exception
End If

They would rather use TryParse because conversions and conversion errors are frequent in a strongly typed environment, and Try/Catch requires more resources.

In most instances there could me more than one reason for an error, and most type of errors can happen less often than TryParse. Then, a simple Boolean is not sufficient. And an error code in an Integer would not be practical. A specific exception, that can have a different message adapted to the specific situation and/or extra properties to give information about what was happening is a lot more useful and enables better handling of the error in the code that traps it.

What do you prefer?

Error 51

... or ...

FileNotFoundException
ex.FileName = "C:\foo\myFile.text"
ex.Stacktrace 'Here is what happened just before the error occured
ex.Source 'Here is the documentation you need to consult to get more details
....
0
 
AndyAinscowCommented:
>>Returning an error code can be typical in other languages and environment, but not in .NET where it is rarely used.

For my understanding there is a significant overhead in using try...catch (stack unwinding...) which ought to make that rather less preferred to returning a value and checking the value returned.  Thowing an exception should be for really exceptional circumstances.
0
 
Jacques Bourgeois (James Burger)PresidentCommented:
Then, why does the framework use Exceptions for almost everything and very few return values such as in the Try...Parse?

Because on a well designed application, errors should be few and happen only occasionnally.
"Thowing an exception should be for really exceptional circumstances"

And error should be an exceptional circumstance, so exceptions have their place. The fact that they provide a lot of information about what was happening makes them a very better tool than simply returning error codes.

In most instances, a good programmer will check for a condition so as to minimize exceptions, such as checking if a file exist instead of relying on a FileNotFoundException.

It is a lot easier for the designer of a class to simply return a number value than it is to build an Exception object with information in it. But when you think that for many the main reason behind classes is code reuse, it make sense to work a little bit more for something that could be used in many places by many different applications.
0
 
dkim18Author Commented:
Thank you.

I opened another post to ask you about the ByRef being used in rare occasion. I would like to read any document or articles about them if there are any.
0
 
AndyAinscowCommented:
>>Then, why does the framework use Exceptions for almost everything and very few return values such as in the Try...Parse?


I could speculate about that but it is well away from the question, which to my understanding seems to be what is the difference between passing parameters ByRef or ByVal.  (Se the first comment in the question about those differences).
0

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

  • 5
  • 5
  • 3
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now