VB code runs different than C# code - Why?

  • Thread starter Thread starter Joe Fallon
  • Start date Start date
J

Joe Fallon

I have a C# class that works correctly.
I translated it to VB and now it runs differently.

The C# class evaluates the Public properties and then executes MyBase.New.
So default values are set first and then MyBase.New reads in new values (if
they exist.)

The VB code does it in reverse.
It excutes MyBase.New and then overwrites the new values when it sets the
defaults.

Can someone please explain what is going on?

The VB class looks like this:
Public Class MyConfig

Inherits SomeConfiguration

Public Sub New()

MyBase.New("SomeStuff")

End Sub

Public MyAddress As String = ""

Public MyName As String = ""

End Class

===========================================================
The C# version is like this:
public class MyConfig: SomeConfiguration

{

public MyConfig() : base("SomeStuff")

{

}


public string MyAddress = "";

public string StoreName = "";

}
 
Joe,
Based on your sample, your description does not make sense? MyAddress &
MyName appear to be fields in the derived class, how is the base class
setting them? Is the base relying on Reflection or something to set them?
Did you mean Fields instead of Properties?

As to the behavior itself: I remember there was one or two discussions about
this during the first .NET beta or shortly after it came out. Basically both
instance & static constructors behave a little differently between C# &
VB.NET. Which one is correct is really hard to say. You could try
groups.google.com, however I'm not sure what you would start looking for.
The C# class evaluates the Public properties and then executes MyBase.New.
Where are the public "properties" in your example, I only see fields, and
you are correct C# sets the fields first, then calls the base, while VB.NET
calls the base first, then sets the fields.
So default values are set first and then MyBase.New reads in new values (if
they exist.)
This seems "backwards" to me, C# is partially constructing an object, then
calls the base constructor, then finishes constructing the derived object?
The VB code does it in reverse.
It excutes MyBase.New and then overwrites the new values when it sets the
defaults.
This seems correct to me, VB.NET is ensuring that the base class is
completely constructed before it constructs the derived object.

Which one is truly "correct" is very must open to debate, which I do not
plan on participating in! :-|

As I stated, there was a discussion a year or two ago, however I don't not
have any links handy.

Hope this helps
Jay
 
Jay,
Your terminology is (of course) correct.you are correct C# sets the fields
first, then calls the base, while VB.NET
calls the base first, then sets the fields.

What I called Public Properties are in fact Public Fields. (My mistake.)

Yes. The Base class is using reflection to set them.

"you are correct C# sets the fields first, then calls the base, while VB.NET
calls the base first, then sets the fields."

OK. They ARE executed differently.

So now the question is: How do I make the VB code behave like the C# code?
In this case the sequence of events is important.
 
Jay,
I hacked up this work around.
It seems to do what I want which is to initialize the value when the Base
class looks for it.

The PropertyGet checks to see if mStoreName Is Nothing, and since it will be
Nothing during the call to MyBase, it initializes it and returns the
"default" value which can then be used in MyBase.
Private mStoreName As String

Public Property StoreName() As String

Get

If IsNothing(mStoreName) Then

mStoreName = "MyStore"

End If

Return mStoreName

End Get

Set(ByVal Value As String)

mStoreName = Value

End Set

End Property
 
Joe,
My only caution would be to disallow Nothing in the property set. Otherwise
if you tried to really set the property to Nothing, it would "fail" as the
Get would then start returning "MyStore"...


If you are already using Reflection, have you considered using an Attribute
on each of the fields/properties that would identify what the "default"
should be, then your base class could use this default attribute instead of
the other value. And you would not need "special" code in VB.NET or
potentially other languages that may use your product?

You could probably even use the System.ComponentModel.DefaultValueAttribute
instead of needing to define your own.

Something like (untested):

Public Class MyConfig
Inherits SomeConfiguration

<DefaultValue("")> _
Public MyAddress As String

End Class

public class MyConfig: SomeConfiguration
{
[DefaultValue("")]
public string MyAddress;

}

Your base constructor would need to check each field/property for the
DefaultValue attribute to know what default value to apply to that
field/property. The derived constructor would leave the fields
"uninitialized" as they were initialized by the base...

Hope this helps
Jay
 
Jay,
You're a genius!

I just re-visited the problem and got stuck using a Boolean field.
My IsNothing hack failed in that case.

I checked here and you came up with a better all-around solution which is to
use
<DefaultValue("")> _
Public MyAddress As String

This works MUCH better.
A lot less code and the default is not used later to overwrite the value I
set during the reflection process
which was the problem when I used Public MyAddress As String = "Some
String"

Thank you so much!
--
Joe Fallon



Jay B. Harlow said:
Joe,
My only caution would be to disallow Nothing in the property set. Otherwise
if you tried to really set the property to Nothing, it would "fail" as the
Get would then start returning "MyStore"...


If you are already using Reflection, have you considered using an Attribute
on each of the fields/properties that would identify what the "default"
should be, then your base class could use this default attribute instead of
the other value. And you would not need "special" code in VB.NET or
potentially other languages that may use your product?

You could probably even use the System.ComponentModel.DefaultValueAttribute
instead of needing to define your own.

Something like (untested):

Public Class MyConfig
Inherits SomeConfiguration

<DefaultValue("")> _
Public MyAddress As String

End Class

public class MyConfig: SomeConfiguration
{
[DefaultValue("")]
public string MyAddress;

}

Your base constructor would need to check each field/property for the
DefaultValue attribute to know what default value to apply to that
field/property. The derived constructor would leave the fields
"uninitialized" as they were initialized by the base...

Hope this helps
Jay


Joe Fallon said:
Jay,
I hacked up this work around.
It seems to do what I want which is to initialize the value when the Base
class looks for it.

The PropertyGet checks to see if mStoreName Is Nothing, and since it
will
be
Nothing during the call to MyBase, it initializes it and returns the
"default" value which can then be used in MyBase.
Private mStoreName As String

Public Property StoreName() As String

Get

If IsNothing(mStoreName) Then

mStoreName = "MyStore"

End If

Return mStoreName

End Get

Set(ByVal Value As String)

mStoreName = Value

End Set

End Property
MyAddress
C#
& fields,
and object,
then don't
not
 
Jay,
It is not working quite right yet.

<DefaultValue("")> _

As you stated my base class needs to evaluate the <DefaultValue("")> _
attribute using reflection. Right now it is coming up with a Null Reference
exception because it does not know what that value is.

Do you have some sample VB code for how to do that?
Thanks.
--
Joe Fallon


Jay B. Harlow said:
Joe,
My only caution would be to disallow Nothing in the property set. Otherwise
if you tried to really set the property to Nothing, it would "fail" as the
Get would then start returning "MyStore"...


If you are already using Reflection, have you considered using an Attribute
on each of the fields/properties that would identify what the "default"
should be, then your base class could use this default attribute instead of
the other value. And you would not need "special" code in VB.NET or
potentially other languages that may use your product?

You could probably even use the System.ComponentModel.DefaultValueAttribute
instead of needing to define your own.

Something like (untested):

Public Class MyConfig
Inherits SomeConfiguration

<DefaultValue("")> _
Public MyAddress As String

End Class

public class MyConfig: SomeConfiguration
{
[DefaultValue("")]
public string MyAddress;

}

Your base constructor would need to check each field/property for the
DefaultValue attribute to know what default value to apply to that
field/property. The derived constructor would leave the fields
"uninitialized" as they were initialized by the base...

Hope this helps
Jay


Joe Fallon said:
Jay,
I hacked up this work around.
It seems to do what I want which is to initialize the value when the Base
class looks for it.

The PropertyGet checks to see if mStoreName Is Nothing, and since it
will
be
Nothing during the call to MyBase, it initializes it and returns the
"default" value which can then be used in MyBase.
Private mStoreName As String

Public Property StoreName() As String

Get

If IsNothing(mStoreName) Then

mStoreName = "MyStore"

End If

Return mStoreName

End Get

Set(ByVal Value As String)

mStoreName = Value

End Set

End Property
MyAddress
C#
& fields,
and object,
then don't
not
 
Why not use your C# class in your VB.Net application? Is there some reason
you don't want to?

Joe Fallon said:
Jay,
It is not working quite right yet.

<DefaultValue("")> _

As you stated my base class needs to evaluate the <DefaultValue("")> _
attribute using reflection. Right now it is coming up with a Null Reference
exception because it does not know what that value is.

Do you have some sample VB code for how to do that?
Thanks.
--
Joe Fallon


Jay B. Harlow said:
Joe,
My only caution would be to disallow Nothing in the property set. Otherwise
if you tried to really set the property to Nothing, it would "fail" as the
Get would then start returning "MyStore"...


If you are already using Reflection, have you considered using an Attribute
on each of the fields/properties that would identify what the "default"
should be, then your base class could use this default attribute instead of
the other value. And you would not need "special" code in VB.NET or
potentially other languages that may use your product?

You could probably even use the System.ComponentModel.DefaultValueAttribute
instead of needing to define your own.

Something like (untested):

Public Class MyConfig
Inherits SomeConfiguration

<DefaultValue("")> _
Public MyAddress As String

End Class

public class MyConfig: SomeConfiguration
{
[DefaultValue("")]
public string MyAddress;

}

Your base constructor would need to check each field/property for the
DefaultValue attribute to know what default value to apply to that
field/property. The derived constructor would leave the fields
"uninitialized" as they were initialized by the base...

Hope this helps
Jay


Joe Fallon said:
Jay,
I hacked up this work around.
It seems to do what I want which is to initialize the value when the Base
class looks for it.

The PropertyGet checks to see if mStoreName Is Nothing, and since it
will
be
Nothing during the call to MyBase, it initializes it and returns the
"default" value which can then be used in MyBase.
Private mStoreName As String

Public Property StoreName() As String

Get

If IsNothing(mStoreName) Then

mStoreName = "MyStore"

End If

Return mStoreName

End Get

Set(ByVal Value As String)

mStoreName = Value

End Set

End Property



--
Joe Fallon


Jay,
Your terminology is (of course) correct.you are correct C# sets the fields
first, then calls the base, while VB.NET
calls the base first, then sets the fields.

What I called Public Properties are in fact Public Fields. (My mistake.)

Yes. The Base class is using reflection to set them.

"you are correct C# sets the fields first, then calls the base, while
VB.NET
calls the base first, then sets the fields."

OK. They ARE executed differently.

So now the question is: How do I make the VB code behave like the C# code?
In this case the sequence of events is important.

--
Joe Fallon



Joe,
Based on your sample, your description does not make sense?
MyAddress
&
MyName appear to be fields in the derived class, how is the base class
setting them? Is the base relying on Reflection or something to set
them?
Did you mean Fields instead of Properties?

As to the behavior itself: I remember there was one or two discussions
about
this during the first .NET beta or shortly after it came out. Basically
both
instance & static constructors behave a little differently between
C#
&
VB.NET. Which one is correct is really hard to say. You could try
groups.google.com, however I'm not sure what you would start looking
for.

The C# class evaluates the Public properties and then executes
MyBase.New.
Where are the public "properties" in your example, I only see fields,
and

So default values are set first and then MyBase.New reads in new
values
(if
they exist.)
This seems "backwards" to me, C# is partially constructing an object,
then
calls the base constructor, then finishes constructing the derived
object?

The VB code does it in reverse.
It excutes MyBase.New and then overwrites the new values when it sets
the
defaults.
This seems correct to me, VB.NET is ensuring that the base class is
completely constructed before it constructs the derived object.

Which one is truly "correct" is very must open to debate, which I
do
not
plan on participating in! :-|

As I stated, there was a discussion a year or two ago, however I don't
not
have any links handy.

Hope this helps
Jay

I have a C# class that works correctly.
I translated it to VB and now it runs differently.

The C# class evaluates the Public properties and then executes
MyBase.New.
So default values are set first and then MyBase.New reads in new
values
(if
they exist.)

The VB code does it in reverse.
It excutes MyBase.New and then overwrites the new values when it sets
the
defaults.

Can someone please explain what is going on?

The VB class looks like this:
Public Class MyConfig

Inherits SomeConfiguration

Public Sub New()

MyBase.New("SomeStuff")

End Sub

Public MyAddress As String = ""

Public MyName As String = ""

End Class

===========================================================
The C# version is like this:
public class MyConfig: SomeConfiguration

{

public MyConfig() : base("SomeStuff")

{

}


public string MyAddress = "";

public string StoreName = "";

}
 
Just educational at this point!
--
Joe Fallon


Brian said:
Why not use your C# class in your VB.Net application? Is there some reason
you don't want to?

Joe Fallon said:
Jay,
It is not working quite right yet.

<DefaultValue("")> _

As you stated my base class needs to evaluate the <DefaultValue("")> _
attribute using reflection. Right now it is coming up with a Null Reference
exception because it does not know what that value is.

Do you have some sample VB code for how to do that?
Thanks.
--
Joe Fallon


Joe,
My only caution would be to disallow Nothing in the property set. Otherwise
if you tried to really set the property to Nothing, it would "fail" as the
Get would then start returning "MyStore"...


If you are already using Reflection, have you considered using an Attribute
on each of the fields/properties that would identify what the "default"
should be, then your base class could use this default attribute
instead
of
the other value. And you would not need "special" code in VB.NET or
potentially other languages that may use your product?

You could probably even use the System.ComponentModel.DefaultValueAttribute
instead of needing to define your own.

Something like (untested):

Public Class MyConfig
Inherits SomeConfiguration

<DefaultValue("")> _
Public MyAddress As String

End Class

public class MyConfig: SomeConfiguration
{
[DefaultValue("")]
public string MyAddress;

}

Your base constructor would need to check each field/property for the
DefaultValue attribute to know what default value to apply to that
field/property. The derived constructor would leave the fields
"uninitialized" as they were initialized by the base...

Hope this helps
Jay


Jay,
I hacked up this work around.
It seems to do what I want which is to initialize the value when the Base
class looks for it.

The PropertyGet checks to see if mStoreName Is Nothing, and since it will
be
Nothing during the call to MyBase, it initializes it and returns the
"default" value which can then be used in MyBase.
Private mStoreName As String

Public Property StoreName() As String

Get

If IsNothing(mStoreName) Then

mStoreName = "MyStore"

End If

Return mStoreName

End Get

Set(ByVal Value As String)

mStoreName = Value

End Set

End Property



--
Joe Fallon


Jay,
Your terminology is (of course) correct.you are correct C# sets the
fields
first, then calls the base, while VB.NET
calls the base first, then sets the fields.

What I called Public Properties are in fact Public Fields. (My mistake.)

Yes. The Base class is using reflection to set them.

"you are correct C# sets the fields first, then calls the base, while
VB.NET
calls the base first, then sets the fields."

OK. They ARE executed differently.

So now the question is: How do I make the VB code behave like the C#
code?
In this case the sequence of events is important.

--
Joe Fallon



message
Joe,
Based on your sample, your description does not make sense? MyAddress
&
MyName appear to be fields in the derived class, how is the base class
setting them? Is the base relying on Reflection or something to set
them?
Did you mean Fields instead of Properties?

As to the behavior itself: I remember there was one or two discussions
about
this during the first .NET beta or shortly after it came out.
Basically
both
instance & static constructors behave a little differently
between
C#
&
VB.NET. Which one is correct is really hard to say. You could try
groups.google.com, however I'm not sure what you would start looking
for.

The C# class evaluates the Public properties and then executes
MyBase.New.
Where are the public "properties" in your example, I only see fields,
and

So default values are set first and then MyBase.New reads in new
values
(if
they exist.)
This seems "backwards" to me, C# is partially constructing an object,
then
calls the base constructor, then finishes constructing the derived
object?

The VB code does it in reverse.
It excutes MyBase.New and then overwrites the new values when it
sets
the
defaults.
This seems correct to me, VB.NET is ensuring that the base class is
completely constructed before it constructs the derived object.

Which one is truly "correct" is very must open to debate, which
I
 
Joe,
attribute using reflection. Right now it is coming up with a Null Reference
exception because it does not know what that value is.
What is coming up with a Null Reference exception?
- your base constructor
- your derived constructor
- your derived classes code

Simply adding the DefaultValue to your class will not do anything.

You will need to add code to your base constructor to look for the attribute
and act accordingly.

You can use the MemberInfo.GetCustomAttributes method to get the list of
custom attributes for a member (field or property).

Hope this helps
Jay

Joe Fallon said:
Jay,
It is not working quite right yet.

<DefaultValue("")> _

As you stated my base class needs to evaluate the <DefaultValue("")> _
attribute using reflection. Right now it is coming up with a Null Reference
exception because it does not know what that value is.

Do you have some sample VB code for how to do that?
Thanks.
--
Joe Fallon


Jay B. Harlow said:
Joe,
My only caution would be to disallow Nothing in the property set. Otherwise
if you tried to really set the property to Nothing, it would "fail" as the
Get would then start returning "MyStore"...


If you are already using Reflection, have you considered using an Attribute
on each of the fields/properties that would identify what the "default"
should be, then your base class could use this default attribute instead of
the other value. And you would not need "special" code in VB.NET or
potentially other languages that may use your product?

You could probably even use the System.ComponentModel.DefaultValueAttribute
instead of needing to define your own.

Something like (untested):

Public Class MyConfig
Inherits SomeConfiguration

<DefaultValue("")> _
Public MyAddress As String

End Class

public class MyConfig: SomeConfiguration
{
[DefaultValue("")]
public string MyAddress;

}

Your base constructor would need to check each field/property for the
DefaultValue attribute to know what default value to apply to that
field/property. The derived constructor would leave the fields
"uninitialized" as they were initialized by the base...

Hope this helps
Jay


Joe Fallon said:
Jay,
I hacked up this work around.
It seems to do what I want which is to initialize the value when the Base
class looks for it.

The PropertyGet checks to see if mStoreName Is Nothing, and since it
will
be
Nothing during the call to MyBase, it initializes it and returns the
"default" value which can then be used in MyBase.
Private mStoreName As String

Public Property StoreName() As String

Get

If IsNothing(mStoreName) Then

mStoreName = "MyStore"

End If

Return mStoreName

End Get

Set(ByVal Value As String)

mStoreName = Value

End Set

End Property



--
Joe Fallon


Jay,
Your terminology is (of course) correct.you are correct C# sets the fields
first, then calls the base, while VB.NET
calls the base first, then sets the fields.

What I called Public Properties are in fact Public Fields. (My mistake.)

Yes. The Base class is using reflection to set them.

"you are correct C# sets the fields first, then calls the base, while
VB.NET
calls the base first, then sets the fields."

OK. They ARE executed differently.

So now the question is: How do I make the VB code behave like the C# code?
In this case the sequence of events is important.

--
Joe Fallon



Joe,
Based on your sample, your description does not make sense?
MyAddress
&
MyName appear to be fields in the derived class, how is the base class
setting them? Is the base relying on Reflection or something to set
them?
Did you mean Fields instead of Properties?

As to the behavior itself: I remember there was one or two discussions
about
this during the first .NET beta or shortly after it came out. Basically
both
instance & static constructors behave a little differently between
C#
&
VB.NET. Which one is correct is really hard to say. You could try
groups.google.com, however I'm not sure what you would start looking
for.

The C# class evaluates the Public properties and then executes
MyBase.New.
Where are the public "properties" in your example, I only see fields,
and

So default values are set first and then MyBase.New reads in new
values
(if
they exist.)
This seems "backwards" to me, C# is partially constructing an object,
then
calls the base constructor, then finishes constructing the derived
object?

The VB code does it in reverse.
It excutes MyBase.New and then overwrites the new values when it sets
the
defaults.
This seems correct to me, VB.NET is ensuring that the base class is
completely constructed before it constructs the derived object.

Which one is truly "correct" is very must open to debate, which I
do
not
plan on participating in! :-|

As I stated, there was a discussion a year or two ago, however I don't
not
have any links handy.

Hope this helps
Jay

I have a C# class that works correctly.
I translated it to VB and now it runs differently.

The C# class evaluates the Public properties and then executes
MyBase.New.
So default values are set first and then MyBase.New reads in new
values
(if
they exist.)

The VB code does it in reverse.
It excutes MyBase.New and then overwrites the new values when it sets
the
defaults.

Can someone please explain what is going on?

The VB class looks like this:
Public Class MyConfig

Inherits SomeConfiguration

Public Sub New()

MyBase.New("SomeStuff")

End Sub

Public MyAddress As String = ""

Public MyName As String = ""

End Class

===========================================================
The C# version is like this:
public class MyConfig: SomeConfiguration

{

public MyConfig() : base("SomeStuff")

{

}


public string MyAddress = "";

public string StoreName = "";

}
 
Jay B. Harlow said:
You will need to add code to your base constructor to look for the attribute
and act accordingly.

I thought I'd tag this on to this thread but any thread you respond to would
do... Jay is there a place I can vote for your getting an MVP++ somewhere?
You always answer clearly and as far as I can see you continue to follow up
until the person gets it.

I just wanted to say thanks for all your help in this newsgroup.
Tom
 
Joe,
Have you tried something like:

Public Class JoeFallon

Public Shared Sub Main()
Dim config As New MyConfig
Debug.WriteLine(config.MyName, "MyName")
Debug.WriteLine(config.MyAddress, "MyAddress")
End Sub

End Class

Public MustInherit Class SomeConfiguration

Protected Sub New(ByVal arg As String)
Dim type As Type = Me.GetType()
For Each field As FieldInfo In type.GetFields()
For Each attribute As DefaultValueAttribute In
field.GetCustomAttributes(GetType(DefaultValueAttribute), False)
field.SetValue(Me, attribute.Value)
Next
Next
End Sub

End Class

Public Class MyConfig
Inherits SomeConfiguration

Public Sub New()
MyBase.New("Something")
End Sub

<DefaultValue("Name")> _
Public MyName As String

<DefaultValue("Address")> _
Public MyAddress As String

End Class

Hope this helps
Jay

Joe Fallon said:
Jay,
It is not working quite right yet.

<DefaultValue("")> _

As you stated my base class needs to evaluate the <DefaultValue("")> _
attribute using reflection. Right now it is coming up with a Null Reference
exception because it does not know what that value is.

Do you have some sample VB code for how to do that?
Thanks.
<<snip>>
 
Hi Tom,
I agree 100%.

Whenever I post a question here I always hope Jay gets to it first!

What I can't figure out is why is he an Outlook MVP instead of VB.Net??
--
Joe Fallon
Access MVP
 
Jay,
I will take a look at this suggestion later.
I tried to get it to work for many hours yesterday and failed too many times
to count.

Every time I took a step forward, I ended up taking 2 backwards.

GetCustomAttributes worked when I used a Property but not when it was a
Field.
(Or maybe the way I used it was what failed.)

This was very frustrating since it worked perfectly in C# and I just wanted
to translate the code toVB.
(I didn't write the C# code - if I did, I probably wouldn't be struggling
with some of these concepts!)
--
Joe Fallon
 
Joe,
It may help if you could share what you have, at least enough to show the
problem. Then I or someone else may be able to identify quicker the change
you need to make...

Hope this helps
Jay
 
Just a quick note for any lurkers.
Jay was kind enough to review my code, re-write a chunk of it so it worked
<g>, and send it back to me.
Of course, it works perfectly!

Jay - thanks again for all your help!
--
Joe Fallon



Jay B. Harlow said:
Joe,
It may help if you could share what you have, at least enough to show the
problem. Then I or someone else may be able to identify quicker the change
you need to make...

Hope this helps
Jay
 
Lurkers,
Important note: I only look at code sent privately that I requested to see!

Thanks for understanding!

Jay
 
Back
Top