VB vs. C# language challenge question

T

Tomasz Jastrzebski

Hello,

Below are to equivalent(?) pieces of C# and VB.Net code
While the C# version compiles with no warning, the VB.Net version does not
compile due to the compiler error BC30149: Class 'c2' must implement 'Sub
m1()' for interface 'i1'.

Does it mean that in VB interface must be implemented, even if it is already
non-explicitly implemented in the base class c1?

How to make this VB code compile *without altering the c1 class* ? - that is
the constraint!
I can not get it compile in VB, while in C# it is just a piece of cake.

Motivation: I want to access base class methods by interface specified in a
derived class.
As strange as it sounds, in C# it works just as expected - test yourself: i1
c = new c2(); c.m1();

Thank you,

Tomasz


// C# version
class c1 {
public virtual void m1() {
}
}

class c2 : c1, i1 {
}

public interface i1 {
void m1();
}

' VB version
Class c1
Public Overridable Sub m1()
End Sub
End Class

Class c2
Inherits c1
Implements i1
End Class

Public Interface i1
Sub m1()
End Interface
 
K

Kevin Yu [MSFT]

Hi Tomasz,

This is a good question. In fact, it is the difference between C# and
VB.NET compilers.

In C#, when you fail to implement an interface, the compiler will
automatically look for a method with the same name as the method in the
interface and map it to the method implementation. In this case, since
there is an m1() method in c1, it will use this method to implement i1.m1().

However, this is not available in VB.NET compiler. That's why a compile
error is generated.

If anything is unclear, please feel free to let me know.

Kevin Yu
Microsoft Online Community Support

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.
Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================

(This posting is provided "AS IS", with no warranties, and confers no
rights.)
 
M

Michael D. Ober

This is actually one of the places where the VB compiler gets it right.
Once you turn on Option Strict and Option Explicit, it makes a lot fewer
assumptions about the code and forces cleaner code. The question you need
to ask yourself is "will the C# compiler always guess right?" The answer is
obviously "no", so having the compiler report an error is actually better
for correctness.

Mike Ober.
 
T

Tomasz Jastrzebski

Well, I see your point. However, lack of this feature, prevents me from
implementing some very important functionality, so I really do not see it as
advantage. I wish I could write code in C# but it is against our standards.

Tomasz
 
T

Tomasz Jastrzebski

Thank you Kevin.
That is what I thought, but I was hoping there was any way around it.
Well, I wish I could program in C#.

Tomasz
 
M

Michael D. Ober

Instead of using an interface, can you make the interface protected so you
have the option? If you want the base implementation, don't do anything.
If you want to use a different implementation in the derived class, shadow
the base, calling the base with mybase.m1() if you need to.

Also, you might want to post this question in


Mike Ober.
 
T

Tomasz Jastrzebski

Protected interface? I am not sure I understand.
Could you show modifying my example accordingly?

Tomasz
 
J

Jon Skeet [C# MVP]

Michael D. Ober said:
This is actually one of the places where the VB compiler gets it right.
Once you turn on Option Strict and Option Explicit, it makes a lot fewer
assumptions about the code and forces cleaner code. The question you need
to ask yourself is "will the C# compiler always guess right?" The answer is
obviously "no", so having the compiler report an error is actually better
for correctness.

In what way is the C# compiler "guessing"? Not only does the name have
to match, but the method signature does too. I don't see how that
counts as guesswork. I wouldn't *hugely* object to C# behaving the same
way that VB.NET does, but I wouldn't say that the C# team got it wrong
in this case.
 
M

Michael D. Ober

The problem is one of verifiable correctness. In this particular case, the
C# compiler allows a "default" implementation that may not always be correct
for the derived class. If the default implementation is correct for the
defined class, then there is no need for an interface definition. If not,
not having the compiler catch this can lead to disaster. This is an error
of omission.

The VB compiler, on the other hand, takes the opposite tack. It forces you
to implement the interface in the derived class. If the default
implementation is correct for the derived class, you simply call it from the
derived class using mybase.defaultmethod(args). The one thing that the VB
IDE does that is useful, but that can lead to the same error of omission
that C# compiler allows is that the VB IDE default configuration is to
actually insert the function prototype for you, but it doesn't put any code
inside the function that would cause the compiler to report a compilation
error, thus allowing the compiler to compile clean but your code not run
properly.

Mike Ober.
 
M

Michael D. Ober

The VB conversion is:

'// C# version
' class c1 {
' public virtual void m1() {
' }
' }

' class c2 : c1, i1 {
' }

' public interface i1 {
' void m1();
' }

' VB version
Class c1
Public Overridable Sub m1()
End Sub
End Class

Class c2
Inherits c1
Implements i1

Public Sub m11() Implements i1.m1
MyBase.m1()
End Sub

End Class

Public Interface i1
Sub m1()
End Interface

The real problem with this is that in VB, interfaces cannot contain default
code. If it needs to, I would implement the classes as follows:

Class c1
Public Overridable Sub m1()
' Default implementation of m1
End Sub
End Class

Class c2
Inherits c1

' To hide the underlying m1 implementation
' Public Shadows Sub m1()
' End Sub

' To extend the underlying my implementation.
' Public Overrides Sub m1()
' End Sub
End Class

Mike.
 
J

Jon Skeet [C# MVP]

Michael D. Ober said:
The problem is one of verifiable correctness. In this particular case, the
C# compiler allows a "default" implementation that may not always be correct
for the derived class. If the default implementation is correct for the
defined class, then there is no need for an interface definition. If not,
not having the compiler catch this can lead to disaster. This is an error
of omission.

It's an error I've never been bitten by, nor have I heard of anyone
else being bitten by it, I have to say. It's also perfectly possible to
have the same error of omission if you only decide to implement the
interface later on, having already implemented methods which happen to
have the same name.

To *really* prevent this from being a problem, you'd have to force
every interface method implementation to explicitly say that it was
implementing the interface, and not just there as a normal part of the
class.

It also makes logical sense for base class methods to "count", as it
were - if you regard an interface as a contract, the class is already
implementing the contract.
The VB compiler, on the other hand, takes the opposite tack. It forces you
to implement the interface in the derived class. If the default
implementation is correct for the derived class, you simply call it from the
derived class using mybase.defaultmethod(args).

Which would, to me, look pretty odd. It's also a pain if the method
implementation is sealed.
The one thing that the VB
IDE does that is useful, but that can lead to the same error of omission
that C# compiler allows is that the VB IDE default configuration is to
actually insert the function prototype for you, but it doesn't put any code
inside the function that would cause the compiler to report a compilation
error, thus allowing the compiler to compile clean but your code not run
properly.

That's where unit tests are important, of course :)

Overall, I think I still prefer the C# way of looking at things.
 
S

Steven Spencer \(Spinalogic\)

Forgive me if this doesn't quite seem relevant here, but in java there is
the concept of an Abstract class. This is where some methods are
implemented and others are left "abstract" much like the interface so that
you can inherit the abstract class yet still need to implement some methods
upon it. Is this feature not possible in .net? or do you need to create a
base class to overload and then a separate interface with the undefined
methods?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top