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做过。
volatile关键字仅在C# http://www.devcity.net/Articles/160/5/article.aspx中提供
我的最爱之一(和我最喜欢的)
在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的唯一值)