Visual Basic中允许哪些内容在C#中被禁止(反之亦然)?

这与代码相关,就像编译器允许您在一种语言中执行的操作一样,但不允许您使用其他语言(例如,在C#中不存在VB中的可选参数)。

如果可能,请提供您的答案的代码示例。 谢谢!

VB和C#对“受保护”的含义有不同的解释。

这是以下复制的解释 :

WebControl的默认构造函数受到保护。

VB和C#对“受保护”的含义有不同的解释。

在VB中,您可以从派生自该类的任何类型的任何方法访问类的受保护成员。

也就是说,VB允许这段代码编译:

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 

因为“Derived1”是一个基础,它可以访问“其他”的受保护成员,这也是一个基础。

C#采用了不同的观点。 它不允许VB进行“侧向”访问。 它表示可以通过“this”或与包含该方法的类相同类型的任何对象来访问受保护的成员。

因为这里的“Foo”在“Derived1”中定义,所以C#只允许“Foo”从“Derived1”实例访问“Base”成员。 “其他”可能不是“Derived1”(例如,它可能是“Derived2”),因此它不允许访问“m_x”。

VB.NET支持CILexceptionfilter,C#不支持:

 Try ... Catch ex As SomeException When ex.SomeProperty = 1 ... End Try 

我很惊讶C#的不安全代码还没有被提及。 这在VB.NET中是不允许的。

VB 9.0编译器自动将文字XML转换为“function构造”语法。 C#编译器不支持这种不错的文字XML语法。

Handles和WithEvents关键字,用于EventHandler的自动连接。

 Private Sub btnOKClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnOK.Click End Sub 

在VB中,您可以使用任何名称的方法实现接口 – 即方法“Class.A”可以实现接口方法“Interface.B”。

在C#中,您必须引入额外级别的间接来实现此目的 – 一种称为 “Class.A”的显式接口实现。

当您希望“Class.A”受到protected和/或virtual (显式接口实现都不是)时,这主要是显而易见的; 如果它只是“私有”你可能只是把它作为显式接口实现。

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 

在IL中,VB直接执行此映射(这很好;实现方法不必共享名称)。

VB允许对虚拟实例方法进行非虚拟调用(在IL中调用),而C#仅允许虚拟调用(IL中的callvirt )。 请考虑以下代码:

 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() 

输出是:

 Derived Base 

这在C#中是不可能的(不使用Reflection.Emit )。

2008年1月,Visual Studio杂志上有一些有用的文章。

  • C#开发人员应该了解VB
  • VB开发人员应该了解C#

VB.NET中允许使用索引属性,但在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 

在我的头顶(4.0之前):

C#中不支持VB语言“function”:

  • 可选参数
  • 后期绑定
  • 不区分大小写

我相信还有更多。 如果您询问每种语言擅长的具体示例,您的问题可能会得到更好的答案。 当与COM交互时,VB当前比C#更好。 这是因为当可选参数可用时,以及在编译时不必绑定到(通常是未知类型)时,COM就不那么令人头疼了。

另一方面,C#在编写复杂逻辑时是优选的,因为它的类型安全性(因为你不能绕过静态类型)及其简洁性。

最后,语言大多是等同的,因为它们只是在边缘上不同。 从function上讲,他们同样有能力。

编辑

要明确的是,我并不是说VB不允许静态输入……只是说C# 不允许你绕过静态类型 。 这使得C#成为某些类型架构的更具吸引力的候选者。 在4.0 C#语言规范中,您可以绕过静态类型,但是您可以通过定义动态代码块来实现,而不是通过声明整个文件“不严格”,这使得它更加有意识和有针对性。

在C#中,您可以将接口中的属性声明为具有“get”,然后在具有get和set的类中实现它。

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

在VB中,相当于用get来解析一个属性就是声明它是ReadOnly。 然后,您无法使实现可写。

 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 

我发现这是VB的严重限制。 我经常想要定义一个允许其他代码只能读取属性的接口,但是我需要在实现的类中使用公共setter,供persistor使用。

VB语言的一个被忽视或简单误解的特性是调用一个具有ByRef参数的函数。 大多数语言仅支持通过引用传递参数的单一方法:即CLR直接支持的方案。

CLR对它支持ByRef参数的值的类型有很多限制,这些限制妨碍了VB成为灵活语言的目标。 因此,编译器竭尽全力灵活并支持ByRef传递的多种途径, 远远超出了CLR原生允许的范围。

C#4 现在支持两种版本的引用传递。 除了从1.0开始的可用之外,当对COM对象进行互操作调用时, ref修饰符现在是可选的。

VB在函数上有可选参数。

C#只能用C#4.0获得这些

在VB中禁止以C#结尾的每一行的分号,当我尝试回到VB.Net时,这总是让我微笑……

C#中的新autoproperties还没有为VB.NET做过。

我的最爱之一(和我最喜欢的)

在VB.Net中,你可以这样构造一个switch / case语句:

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

这允许您通过开关而不是各种if / else块来评估一些复杂的评估。 你不能在C#中做到这一点。

在C#中,您必须先分配变量才能使用它。 我想你可以关闭它,但这是默认行为。

所以这样的事情:

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

不允许,但VB等效。

正如Chris Dunaway所提到的,VB.NET具有允许您定义函数和数据的模块。

VB.NET具有用于链接到DLL中的方法的VB6语法。 例如:

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

(虽然实际的声明可能必须是Marshalled)


c#我认为全局变量不存在

当转换为整数时VB.Net中的True将转换为-1,而在C#中它将转换为1。

此外,VB.Net中的NOT关键字确实是一个按位NOT(如在C#’〜’中),而不是逻辑NOT(C#’!’)。

而对于AND和OR运算符,VB.Net已经有逻辑运算符AndAlso和OrElse,它们是真正的逻辑运算符和短路,仍然没有逻辑NOT。

这在处理Win32 API时尤为重要,其中假设如果结果为True则NOT会否定它,这是错误的,因为在C中= = 1,因此在1上的按位NOT也是一个真值(这实际上可能就是为什么在VB中为true == -1,因为这是一个按位NOT将导致0的唯一值)