【问题标题】:Converting C# knowledge to VB.NET any potential problems?将 C# 知识转换为 VB.NET 有什么潜在的问题吗?
【发布时间】:2009-08-26 20:25:20
【问题描述】:

我的团队成员对 C# 非常熟悉,但我们需要在 VB.net 中编写一个项目。在 C# 中思考并在运行中转换为 VB 会有多难? 这可行吗?

您能否列出我们可能遇到的问题?

我听说 VB.net 没有闭包。 .net 3.5 仍然如此吗?

【问题讨论】:

  • 这并不值得回答,但是保持 VB.NET 的视觉组织比 C# 更困难,因为关键字更大且长度更多样化,并且没有括号(有助于垂直空间)。用 VB.NET 和 C# 编写的方法并排放置通常会使 C# 的逻辑看起来更清晰。
  • 为什么有这个要求?这没有多大意义。您能否提供更多背景信息,以免我们摸不着头脑?
  • 我正在考虑一个有这种非功能性需求的项目。
  • 我不同意 yoooder - 大多数人发现 vb.net 更具可读性,因为它更冗长。我相信这里的每个人都会不同意,因为 c# 更酷。

标签: c# .net vb.net c#-to-vb.net


【解决方案1】:

如果您以 C# 的心态接触 VB.Net,最好在项目中设置以下选项

  • 选项严格开启
  • 选项显式打开
  • 选项推断开启

这实质上移除了 VB.Net 的后期绑定语义,并强制它成为一种严格类型化的语言。这将使它更接近 C# 语义(无论如何仍然不准确)。

VB.Net 从 Visual Studio 2008 / .Net Framework 3.5 版本开始支持 Lambda 表达式(因此也支持闭包)。不是表达也不是陈述。直到 VS2010 / .Net Framework 4.0 才支持语句 lambda。虽然您可以使用 4.0 编译器来降低 2.0 框架的目标。

【讨论】:

    【解决方案2】:

    由于 C# 和 VB.NET 使用相同的框架并编译成非常相似的 IL 代码,因此您可以免费获得很多。相反,编写基本语法并不难。

    C# 语法更旨在显示正在发生的事情,而 VB 语法通常隐藏一些细节,因此 C# 程序员已经熟悉了一些对 VB 程序员来说可能并不明显的概念。在某些方面,学习 C# 比学习 VB 本身更好地了解 VB 的工作原理......

    我经常根据我的 C# 知识在不同的论坛上回答 VB.NET 问题,而我自己除了用 VB.NET 编写简短的测试程序外,还没有写过任何东西。

    在 VB 中当然有一些怪癖需要注意。例如,总是将两个操作数都转换为双精度的 / 运算符,或使用 VB 特定比较代码而不是为 .NET 类中的相等运算符指定的比较的 = 操作数。

    【讨论】:

    • +1 我总是告诉学习 .NET 平台的人(尤其是那些刚接触 OOP 的人)首先学习 C#,然后在必要时转到 VB。 VB 没有错,但由于您提到 C# 的原因,您可以更清楚地了解 IMO 框架中发生的事情。
    • @jmgant:我不同意,VB.NET 提供了比 C# 更低的入门门槛,并且可以让你更快地在 .NET 世界中进行编码——尽管留在 VB.NET 的理由很快就会消失。我通常建议从 VB.NET 开始以加快速度,然后跳转到 C# 以在剩下的过程中拉开帷幕。
    • @jmgant & Yoooder:我认为这两种方式都有优点,并且每种方式都更适合不同的人,这取决于他们是想放松还是沉迷其中。:)
    • 好答案。我和 Guffa 一样,但反过来。我用 VB 编写代码,但不时回答关于 SO 的 C# 问题。表明 VB 与 C# 的争论是徒劳的,因为这两种语言实际上非常接近(并且将来会变得更接近)。你不能说一种语言不好(或好)而不说另一种语言也是;-)
    【解决方案3】:

    VB.NET 试图掩盖的一个领域是处理事件。其他人简要地谈到了一些差异,但这里有更多关于它们的内容:

    VB.NET 为引发事件的字段提供了一个WithEvents 关键字。如果该字段声明为WithEvents,那么您可以在签名与事件兼容的方法末尾添加Handles field.Event;该方法将自动成为事件的委托,无需手动 AddHandler 和 RemoveHandler(+= 和 -=)。

    Private WithEvents SomeField
    Public Sub SomeField_SomeEvent(sender as Object, e as EventArgs) Handles SomeField.SomeEvent
        Console.Writeline("SomeEvent occured")
    End Sub
    

    事件声明和引发事件被简化了一点。 VB.NET 不要求您在通知侦听器之前检查事件是否为空:

    Public event SomeEvent as EventHandler(of SomeEventArg)
    Public Sub SomeMethod()
        RaiseEvent SomeEvent(Me, new EventArgs)
    End Sub
    

    VB.NET 中事件的一个“隐藏”特性是访问底层的MulticastDelegate,以执行类似GetInvocationList() 的操作 注意:事件被命名为SomeEvent 和访问代码multicastdelegate 调用了一个名为SomeEventEvent的不可见字段:

    Public event SomeEvent as EventHandler(of SomeEventArg)
    Public Sub SomeMethod()
        // Note that SomeEvent's MulticastDelegate is accessed by appending
        // another "Event" to the end, this sample is redundant but accurate.
        // If the event was named ListChanged then it would be ListChangedEvent
        dim invocationList = SomeEventEvent.GetInvocationList()
    End Sub
    

    【讨论】:

    • 最后一点与 VB.NET 本身无关。这是一个框架特性;甚至没有任何特定于 VB 的语法。
    • @Adam:VB.NET 特定部分将“事件”附加到事件名称以访问多播委托。
    【解决方案4】:

    我发现的最大问题之一是 VB 明显冗长。它有所有这些大关键字,如 MustInherit、NotInheritable、MustOverride 等,而 C# 中只有 sealed、abstract 和 virtual。您必须对所有内容都有一个End(End Sub、End Function、End While、End Namespace、End Class 等)并且您必须使用 ReadOnly 关键字显式标记只读属性;简单地省略二传手不会飞。还要记住AndAlso 和OrElse 而不是更直观(但非短路)的And 和Or,以及诸如Is Nothing 和IsNot Nothing 之类的东西而不是== null 或!= null。

    这些都不一定是语言的问题,但如果您习惯于 C# 的相对简单性,VB 代码对您来说可能看起来像是一大堆额外的东西。

    【讨论】:

    • 是的,VB 确实有点冗长,但如果打字是你编程中最重要的部分,那么你所处理的项目就不够具有挑战性...... :)
    • VB.NET 更健谈,但也更具描述性。如果你刚开始使用 .NET,很高兴看到“Inherits BaseClass Implements IDisposable Implements ISomeInterface 比 : BaseClass IDisposable ISomeInterface; 特别是当你试图让代码编译并且某些东西只是乱序时。过了一段时间它变得很烦人而且C#中的快捷键越来越吸引人
    • @Guffa +1,有趣...虽然这真的不只是打字,而是阅读、理解和重构。
    • @Guffa - 很好的评论。但这真的很烦人。我曾在 c# 和 vb.net 中处理过大型项目。我为烦人的打字提供的最好的例子是方法的参数(又名 subs 和函数 :)) public string SomeMethod(string var1, string var2, int var3) 很容易。 public Function SomeMethod(ByVal var1 As string, ByVal var2 As string, ByVal var3 As Integer) 作为字符串。哎哟。这些想法发生的速度比我输入的要快:)
    【解决方案5】:

    Visual Studio 杂志早在 2008 年 1 月就有一些有用的文章。

    您可能也对“what's allowed in VB that is prohibited in C# (or vice versa)”这个问题感兴趣

    【讨论】:

      【解决方案6】:

      这里没有提到的一点是,C# 中的字段初始值设定项在基构造函数之前运行,而 VB 中的字段初始化器在基构造函数和派生类构造函数的第一个“真实”语句之间运行(在基构造函数之后) -构造函数调用,如果有的话)。这使得派生类中的字段初始值设定项可以使用基类成员(可能已经使用传递给构造函数的参数进行了初始化),但也意味着如果对象的基类构造函数在之前的任何位置传递自身它返回,部分构造的对象可能会在所有字段初始化程序运行之前被使用。在 C# 中,所有字段初始值设定项都将在基本构造函数开始执行之前运行,但没有一个字段初始值设定项能够使用部分构造的对象。

      PS——如果 C# 背后的任何 Microsoft 人员读到此内容,是否会为字段声明添加上下文相关关键字以指定是否应在基本构造函数之前或之后处理它们,或者可能有它们由可以从构造函数调用的一些特殊方法执行,该方法可以包装在 try-finally 块中(因此可以清理由此分配的任何 IDisposables),并且还可以使用传递给构造函数的参数?

      【讨论】:

        【解决方案7】:

        我发现这是一篇强调差异的方便文章。我是一个 vb.net 程序员,这有助于我弄清楚 c# 代码,所以我相信它会以另一种方式工作!

        http://www.codeproject.com/KB/dotnet/vbnet_c__difference.aspx

        【讨论】:

        • 令人惊讶的是,VB.NET 的 AddHandler 和 RemoveHandler 与 C# 的 "+=" 和 "-=" 不同。当从 C# 转到 VB.NET 时,另一件很麻烦的事情是“Handles”关键字,它遵循 VB 中的一个方法,订阅一个事件。
        • 好点。使用 AutoEventWireup 去 C# 方向并且不使用“Handles”也很棘手。这是一篇解释事情的好文章。 odetocode.com/blogs/scott/archive/2006/02/16/2914.aspx
        【解决方案8】:

        就像任何语言(人类或计算机)一样,您首先学会“在脑海中翻译”,然后您最终开始用另一种语言“思考”。

        您的团队越快实现这一飞跃越好。因此,请按照专家告诉您学习人类语言的相同方式进行:真实世界的示例和沉浸式体验。

        网上有一些 C# 到 VB.NET 的转换实用程序,所以首先让团队用 C# 编写,转换为 VB.NET,然后清理它。 (转换实用程序的质量各不相同,并且有一些限制,尤其是对于较新的语言功能。)

        一旦他们掌握了基本的“语法”,就将它们放入 VB.NET 100% 中。

        我每天都使用这两种方法,经常同时在不同的代码窗口中使用,并且在上下文切换或在每种情况下都做“正确的事情”没有问题。

        【讨论】:

          【解决方案9】:

          除了 Jared 已经提到的内容之外,您这样做应该没有问题。唯一的其他刺激来源是奇怪的默认值。例如。您知道 VB.NET 项目默认隐藏解决方案资源管理器中的引用节点吗? (您必须选择 ShowAllFiles 才能看到它)。

          【讨论】:

            【解决方案10】:

            感谢这个问题的年代,这个问题现在可能已经广为人知了,但我将添加一个我在像 C# 用户一样编写 VB.NET 方面看到的最大问题:

            Nothing不是null,而是default(T)

            这意味着……

            Dim a As Integer = Nothing
            Dim b As Integer? = Nothing 
            

            ...是完全有效的,并且实际上意味着...

            int a = default(int);    // 0
            int? b = default(int?);  // null
            

            John M Gant's answer 提到了一个事实,即有专门的关键字用于比较 Nothing-meaning-null -- Is Nothing 和 IsNot Nothing 但是,如果你忘记并使用 =,你可能会得到一个难以追踪的意外结果:

            Dim a As Integer? = Nothing
            If a = Nothing Then Console.WriteLine("a = Nothing")
            If a <> Nothing Then Console.WriteLine("a <> Nothing")
            If a Is Nothing Then Console.WriteLine("a Is Nothing")
            If a IsNot Nothing Then Console.WriteLine("a IsNot Nothing")
            
            'Output:
            'a Is Nothing
            

            这至少被编译器警告(BC42037 和 BC42038)捕获,因此您可能希望将这些警告强制为 VBPROJ 文件中的错误。

            【讨论】:

              【解决方案11】:

              我认为 C# 到 VB.NET 不会太痛苦,这只是学习新语法的一个案例。在当前版本中,两种语言的功能相当接近。

              反过来(VB.NET 到 C#)可能会更难,因为人们可能习惯于使用“我的”命名空间和其他东西来让 VB6 开发人员有宾至如归的感觉。

              【讨论】:

                【解决方案12】:

                您必须注意一些细微的差异。例如,VB.Net 没有短路 if 语句的概念(我被更正,显然它确实如此)。如果它只是一个短期项目,你可能不会有问题,但不同的语言确实有不同的方法来解决相同的问题。这方面的一个例子是 Python 程序员谈论以“pythonic”方式做事。他们在 Dreaming in Code 一书中谈到了这个概念,其中 Java 程序员试图使用 Python 语法对 Java 进行编程。它导致解决问题需要很长的路要走。 C# 和 VB.Net 会发生这种情况吗?很难说,它们都使用底层框架,因此差异不会很大,但尝试学习如何按预期方式使用 VB.NET 仍然会有所帮助。

                编辑:很明显,它确实有短路的概念,但默认情况下它不会像 C# 那样做。这只是进一步证明了学习语言功能如何长期有益的意义。

                【讨论】:

                • 我很高兴短期循环被纳入讨论。我团队中的每个人都希望if x IsNot Nothing And x.method() 不会抛出空指针异常。
                • 语言的结构并没有太大的不同,回溯它们在 ALGOL 中有一个共同的祖先。 C# 编写代码的方式通常可以很好地转换为 VB。
                • 我明白你在说什么,但这种说法适用于很多语言。 C++、C#、Java,不胜枚举。它们与 Perl 相比更相似,但存在差异。
                【解决方案13】:

                我认为这不会太难。 VB.NET 和 C# 是彼此接近的语言,只是语法确实不同。当然,您的团队需要一些时间来适应新语言,但我认为您不会遇到大问题。

                哦,VB.NET 确实有闭包。它缺少 C# 中的一些其他功能,例如 yield 关键字、多语句 lambda 和 auto 属性,但没有什么非常重要的。

                【讨论】:

                • VB9 有单行函数闭包。 VB10 具有与 C# 相同的闭包。
                • @Strilanc,Lambda 和闭包是不同的概念。 VB.Net 的闭包实现在 9.0 和 10.0 之间没有变化。不过 lambda 实现差异很大。
                【解决方案14】:

                如果您不想编写 vb.net 代码,一个选择是用 C# 编写您的项目,编译它,然后使用 Reflector 查看 vb.net 等效项的外观。无论如何,这一切都编译为 MSIL!

                【讨论】:

                • 有时可以。重新生成的代码充其量是不确定的,如果您正在谈论一个可能相当大的类,那么它可能会很痛苦。
                • @Yooder,我从未在我使用过的任何东西中看到过这种情况。我发现它是一个很棒的学习工具。
                • 它只适用于小样本;每当我需要导出一个相当大的程序集时,我发现自己必须纠正相当数量的问题。也许它特定于我正在使用的框架版本
                • 是的,我相信你必须做出改变,尤其是在更复杂的场景中。例如,我不确定静态类将如何转换为 vb.net,或者在 c# pre 4.0 中如何处理可选参数。不管怎样,还是很方便的!
                • @ScottE,静态类最类似于 VB 中的模块。您不能实例化模块,并且它们的所有方法都是自动静态的(并且不能这样显式声明)。
                猜你喜欢
                • 1970-01-01
                • 2011-10-19
                • 2012-01-11
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多