14

This is code-related as in what the compiler will allow you to do in one language, but not allow you to do in another language (e.g. optional parameters in VB don't exist in C#).

Please provide a code example with your answer, if possible. Thank you!

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
Alex
  • 75,813
  • 86
  • 255
  • 348
  • Could you clarify some? Allowed as in features available, technical differences in the language and compiler, or something else? – JoeCool Jun 08 '09 at 19:17
  • There are differing answers for different versions for this question; what version(s) are you referring to? – Paul Sonier Jun 08 '09 at 19:18
  • Question is a bit vague, they are different languages, but can both use the .NET framework. Perhaps you mean, why would you choose one language over the other? – D'Arcy Rittich Jun 08 '09 at 19:18
  • I'm trying to figure out what major dialect differences are, as I'm only familiar with C# and I've read in some places "this is only possible in VB" or vice versa for C#. So I thought this would be a good time to get some clarification :) – Alex Jun 08 '09 at 19:23

21 Answers21

17

VB.NET has support for CIL Exception Filters, C# doesn't:

Try 
  ...
Catch ex As SomeException When ex.SomeProperty = 1
  ...
End Try 
bzlm
  • 9,626
  • 6
  • 65
  • 92
  • Hey, that's pretty cool. I think I'm going to convert all my source from C# to VB now! Seriously, though, that's cool, hope the C# team picks up on this. – Michael Meadows Jun 08 '09 at 19:37
  • 6
    +1 and here's where the NET CLR team blog explains why exception filters are useful http://blogs.msdn.com/clrteam/archive/2009/02/05/catch-rethrow-and-filters-why-you-should-care.aspx – MarkJ Jun 08 '09 at 20:11
  • 2
    Updated link for the .Net CLR blog post [Catch, Rethrow and Filters - Why you should care?](http://blogs.msdn.com/b/dotnet/archive/2009/02/05/catch-rethrow-and-filters-why-you-should-care.aspx). Also of interest [The good and the bad of exception filters](http://blogs.msdn.com/b/dotnet/archive/2009/08/25/the-good-and-the-bad-of-exception-filters.aspx) – MarkJ Aug 16 '12 at 11:14
13

I'm surprised that C#'s unsafe code has not been mentioned yet. This is not allowed in VB.NET.

Tomas Aschan
  • 58,548
  • 56
  • 243
  • 402
11

The VB 9.0 compiler automatically translates literal XML into "functional construction" syntax. The C# compiler does not support this nice literal XML syntax.

dss539
  • 6,804
  • 2
  • 34
  • 64
11

Handles and WithEvents keywords for automatic wiring of EventHandlers.

Private Sub btnOKClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnOK.Click
End Sub
Lurker Indeed
  • 1,521
  • 1
  • 12
  • 21
  • 1
    IMHO, these are the right approach to handling events, except that there should be language support for nuking all event subscriptions held on behalf of an object. Objects which are Disposed should nearly always do so; failure to do so can cause memory leaks. – supercat Dec 21 '10 at 23:18
10

In VB you can implement an interface with a method of any name - i.e. a method "Class.A" can implement interface method "Interface.B".

In C#, you would have to introduce an extra level of indirection to achieve this - an explicit interface implementation that calls "Class.A".

This is mainly noticeable when you want "Class.A" to be protected and/or virtual (explicit interface implementations are neither); if it was just "private" you'd probably just leave it as the explicit interface implementation.

C#:

interface IFoo {
    void B();
}
class Foo : IFoo { 
    void IFoo.B() {A();} // <====  extra method here
    protected virtual void A() {}
}

VB:

Interface IFoo
    Sub B()
End Interface
Class Foo
    Implements IFoo
    Protected Overridable Sub A() Implements IFoo.B
    End Sub
End Class

In the IL, VB does this mapping directly (which is fine; it is not necessary for an implementing method to share a name).

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
8

VB allows nonvirtual calls to virtual instance methods (call in IL), whereas C# only allows virtual calls (callvirt in IL). Consider the following code:

Class Base
    Public Overridable Sub Foo()
        Console.WriteLine("Base")
    End Sub

    Public Sub InvokeFoo()
        Me.Foo()
        MyClass.Foo()
    End Sub
End Class

Class Derived : Inherits Base
    Public Overrides Sub Foo()
        Console.WriteLine("Derived")
    End Sub
End Class

Dim d As Base = New Derived()
d.InvokeFoo()

The output is:

Derived
Base

That's not possible in C# (without resorting to Reflection.Emit).

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • C# does also, but only in limited circumstances. You can make a non-virtual call to the base class implementation of a virtual method (and not only from within an override). – Ben Voigt Jul 22 '13 at 03:07
7

There were some useful articles in Visual Studio magazine back in Jan 2008.

MarkJ
  • 30,070
  • 5
  • 68
  • 111
6

In C# you can declare a property in an interface as having a 'get', and then implement it in a class with a get and set.

public interface IFoo {
  string Bar {get;}
}

public class Foo : IFoo {
  public string Bar {get; set;}
}

In VB, the equivalent to declating a property with a get would be to declare it ReadOnly. You can't then make the implementation writable.

Public Interface IFoo 

  ReadOnly Property Bar() As String

End Interface

Public Class Foo 
   Implements IFoo

  Public Property Bar() As String Implements IFoo.Bar  'Compile error here'

End Class

I find this to be a severe limitation of VB. Quite often I want to define an Interface that allows other code only to be able to read a property, but I need a public setter in the implemented class, for use by the persistor.

Josh Lee
  • 171,072
  • 38
  • 269
  • 275
Richard Pawson
  • 1,494
  • 1
  • 10
  • 15
6

One of the overlooked or simply misunderstood features of the VB language is calling a function which has a ByRef parameter. Most languages support only a single method of passing parameters by reference: that is the scenarios directly supported by the CLR.

The CLR has a lot of restrictions on the type of values it supports for ByRef parameters and these restrictions get in the way of VB’s goal to be a flexible language. Hence the compiler goes to great lengths to be flexible and support multiple avenues of ByRef passing, much beyond what the CLR natively allows.

C# 4 now supports two versions of reference passing. In addition to the one available since 1.0 the ref modifier is now optional when making an interop call to a COM object.

MarkJ
  • 30,070
  • 5
  • 68
  • 111
  • Too bad they don't allow a similar approach to struct properties (e.g. if "foo" is a read/write property of a struct type, translate `mything.foo.x=5` as `temp=mything.foo : temp.x=5 : mything.foo = temp` – supercat Dec 21 '10 at 23:22
6

Off the top of my head (pre 4.0):

VB language "features" not supported in C#:

  • Optional Parameters
  • Late Binding
  • Case insensativity

I'm sure there's more. Your question might get better answers if you ask for specific examples of where each language excels. VB is a currently better than C# when interacting with COM. This is because COM is much less of a headache when optional parameters are available, and when you don't have to bind to the (often unknown type) at compile time.

C# on the other hand, is preferable by many when writing complex logic because of its type safety (in that you can't bypass static typing) and its conciseness.

In the end, the languages are mostly equivalent, since they only differ on the fringes. Functionally, they are equally capable.

EDIT

To be clear, I'm not implying that VB doesn't allow static typing... simply that C# doesn't [yet] allow you to bypass static typing. This makes C# a more attractive candidate for certain types of architectures. In the 4.0 C# language spec, you can bypass static typing, but you do it by defining a block of dynamic code, not by declaring the entire file "not strict," which makes it more deliberate and targeted.

Michael Meadows
  • 27,796
  • 4
  • 47
  • 63
  • Didn't know. I'll take it out. – Michael Meadows Jun 08 '09 at 19:23
  • 2
    C# 4.0 has optional parameters. They didn't want them, but not having them makes legacy COM a hassle. – Brian Jun 08 '09 at 19:28
  • @Brian, I knew that was coming in 4.0. In fact, one of the focuses of the language changes in C# for 4.0 seems to be to bridge the COM gap, which makes the languages even more equivalent. I'm not sure why they don't try to specialize then languages more instead of making them more similar... as a developer, I don't need two languages that are so similar that my only reason to choose one over the other is subjective (my affinity for semicolons or the words "Then" and "End"). – Michael Meadows Jun 08 '09 at 19:34
  • 1
    I'd remove the comment about static typing. `Option Strict` allows typing that is just as strict as C#'s. VB, for all intents and purposes, is type safe. – Konrad Rudolph Jun 08 '09 at 19:48
  • @Konrad Rudolph, it's true, however, that you can bypass static typing in VB, and you cannot in C#. I did intentionally choose the word "bypass". Even that, though, is going away in 4.0 with the "dynamic" keyword. – Michael Meadows Jun 08 '09 at 19:57
  • 1
    The thought of case insensitive code makes me shudder. But I guess it is all a matter of what you are used to. And I guess it's kind of funny, because the exact opposite is true for sql, the thought of writing a case sensitive sql query makes me shudder. – Kevin Jun 08 '09 at 21:16
  • I changed it from "VB language benefits" to "VB language 'features'" when I added case insensitivity. :) A lot of the language differences in VB seem to be throwbacks to support migrated VB6 code that they're just stuck with now. The funny thing is that it has almost come full circle, with C# adopting a lot of what we used to scoff at as legacy features in VB. – Michael Meadows Jun 08 '09 at 21:26
  • VB.NET with `Option Strict On` is *still* not as type-safe as C#. One example off the top of my head: non-string types are silently converted to strings if they are embedded in a string concatenation expression. – Christian Hayter Jan 27 '10 at 09:56
  • @Christian: as they are in C#. No difference. In fact, VB allows the use of an extra concatenation operator which doesn’t exist in C#, making string concatenations even *more* unambiguous (visually) than in C#. – Konrad Rudolph Jan 27 '10 at 11:20
6

Indexed properties are allowed in VB.NET, but not in C#

    Private m_MyItems As New Collection(Of String)
    Public Property MyItems(ByVal index As Integer) As String
        Get
            Return m_MyItems.Item(index)
        End Get
        Set(ByVal value As String)
            m_MyItems.Item(index) = value
        End Set
    End Property
slolife
  • 19,520
  • 20
  • 78
  • 121
  • @R.Bemrose: That's not the same thing! It is similar, but in C# you can only have one indexer. IIRC, in VB.Net you can have any number of properties that have indexes. – Chris Dunaway Jun 08 '09 at 21:25
5

VB and C# have different interpretations of what "protected" means.

Here's an explanation copied below:

The default constructor for WebControl is protected.

VB and C# have different interpretations of what "protected" means.

In VB, you can access a protected member of a class from any method in any type that derives from the class.

That is, VB allows this code to compile:

class Base
    protected m_x as integer
end class

class Derived1
    inherits Base
    public sub Foo(other as Base)
        other.m_x = 2
    end sub
end class

class Derived2
    inherits Base
end class

Because a "Derived1" is a base, it can access protected members of "other", which is also a base.

C# takes a different point of view. It doesn't allow the "sideways" access that VB does. It says that access to protected members can be made via "this" or any object of the same type as the class that contains the method.

Because "Foo" here is defined in "Derived1", C# will only allows "Foo" to access "Base" members from a "Derived1" instance. It's possible for "other" to be something that is not a "Derived1" (it could, for example, be a "Derived2"), and so it does not allow access to "m_x".

Community
  • 1
  • 1
Tom Ritter
  • 99,986
  • 30
  • 138
  • 174
  • If I'm reading this correctly, C#'s protected internal gets around this. – Powerlord Jun 08 '09 at 20:46
  • @R. Bemrose - my understanding is that the two are orthogonal; the protected issue would still apply across multiple assemblies. – Marc Gravell Jun 08 '09 at 21:08
  • My vb.net2010 won't accept that, and I find it hard to imagine that it would. Part of the purpose of Protected is to forbid sideways access. Perhaps you're thinking of the fact that a class which declares private or protected members can access those members in other instances of the same class or derivatives. – supercat Dec 21 '10 at 23:14
5

The volatile keyword is only available in C# http://www.devcity.net/Articles/160/5/article.aspx

Kane
  • 16,471
  • 11
  • 61
  • 86
5

One of my favorites (and bummers)

In VB.Net you can struture a switch/case statement as such:

Select Case True

   Case User.Name = "Joe" And User.Role = "BigWig" And SecretTime = "HackerTime"
      GrantCredentials()

End Select

which allows you to evaluate some complex evaluations through a switch instead of a variety of if/else blocks. You cannot do this in C#.

Dillie-O
  • 29,277
  • 14
  • 101
  • 140
  • This syntax has always thrown me, as it's nothing more than an If statement masquerading as a Case. – Powerlord Jun 08 '09 at 20:53
  • 1
    My initial reaction is "Holy crap is that ugly code. I would slap someone for writing that." But I'm trying to be fair and consider if it would ever be useful – Kevin Jun 08 '09 at 21:12
  • You can run into situations where where you evaluate clause A, then go down and evaluate clause B and C if A is true or evaluate C and D if A is false, and so on. Being able to line them out in single line evaluations to a single true/false helps readability. – Dillie-O Jun 08 '09 at 22:14
  • I'm doing some ugly nested case-if statements in C# right now and I find myself wishing I could do this... – muusbolla Jul 08 '09 at 15:47
  • 3
    VB's ability to do `Select Case` on pretty much anything is nice too – Pondidum Dec 04 '09 at 11:51
5

VB has optional parameters on functions.

C# will only get these with C# 4.0

rein
  • 32,967
  • 23
  • 82
  • 106
4

The semi-colon that ends up every line in C# is prohibited in VB, and that always makes me smile when I try going back to VB.Net...

Gad
  • 41,526
  • 13
  • 54
  • 78
4

The new autoproperties in C# have not been done for VB.NET yet.

TheTXI
  • 37,429
  • 10
  • 86
  • 110
  • VB.net added auto-properties for the simple "get/set" case, but I wish both languages would facilitate defining a read-only auto-property with a specified backing variable. – supercat Feb 04 '12 at 21:34
3

In C# you have to assign your variable before you can use it. I think you can turn this off, but it's the default behavior.

So something like this:

int something;
if (something == 10)
{ ... }

Isn't allowed, but the VB equivalent would be.

Joseph
  • 25,330
  • 8
  • 76
  • 125
  • It's even stranger when you consider that Java, the language C# copied, allows that (ints have a default value of 0). At a guess, MS didn't like that Java allowed you to do that so C# doesn't allow it. But, since VB6 did it, they left it in Vb.NET. – Powerlord Jun 08 '09 at 20:51
  • Pretty sure this is by design and part of the strictness of c#. Beats C which just left a random value in there, which of course, was _usually_ 0, until, that is, you put your program into production. – FastAl Jun 15 '11 at 16:06
3

As Chris Dunaway mentioned, VB.NET has Modules which allow you to define functions and data.

VB.NET has the VB6 syntax for linking to methods in DLLs. For example:

Declare SetSuspendState Lib "powrprof" As Function (byval hibernate as Int32, byval forceCritical as Int32, byval disableWakeEvent) as Int32

(Although that actual declaration might have to be Marshalled)


  • Modules - aaargh! Now if they added an attribute that removed module members from the global namespace, they would be genuinely useful. Please someone tell me it exists and I just haven't found it yet. :-( – Christian Hayter Jan 27 '10 at 09:59
  • 1
    C# allows modules - they're called static classes if memory serves - but it's the exact same thing. – FastAl Jun 15 '11 at 16:08
2

Global variables don't exist in c# i think

Noctris
  • 554
  • 3
  • 17
  • Good call, and global methods... although I say good riddance to both. – Michael Meadows Jun 08 '09 at 19:42
  • 3
    Nor do they exist in VB.Net either! VB.Net allows you to have a Module which kind of looks like global variables, but in reality it is just a class under the hood with all static members. – Chris Dunaway Jun 08 '09 at 21:23
  • 1
    @Chris Dunaway, regardless of how it's wired, it is still treated as global by VB. Both the VB and C# compilers are chock full of "tricks" that make the languages appear to do more than the CLI supports. In the end, though, if I declare a variable "public i as Int32" in a public module, I can access it "Debug.WriteLine(i)" from anywhere in VB. – Michael Meadows Jun 09 '09 at 13:35
  • C# and VB both allow globals - Public variable in a static class. Just like public var in a shared class in vb. Who cares about the syntax, it's a global. – FastAl Jun 15 '11 at 16:07
1

True in VB.Net when converted to an integer will convert to -1 while in C# it will convert to 1.

Furthermore the NOT keyword in VB.Net is indeed a bitwise NOT (as in C# '~'), and not a logical NOT (C# '!').

While for the AND and OR operators, VB.Net has already logical operators AndAlso And OrElse which are true logical operators and short circuit, still there is no logical NOT.

This is especially important when dealing with the Win32 API, in which doing NOT on the result assuming that if the result is True the NOT will negate it, is wrong, since in C true == 1 and therefore a bitwise NOT on 1 is also a true value (and this is in fact probably the reason why in VB true == -1, as this is the only value on which a bitwise NOT will result in 0)

yoel halb
  • 12,188
  • 3
  • 57
  • 52