Что разрешено в Visual Basic, что запрещено в C# (или наоборот)?

Это связано с кодом, как в том, что компилятор позволит вам делать на одном языке, но не позволяет делать на другом языке (например, необязательные параметры в VB не существуют в C#).

Пожалуйста, предоставьте пример кода с вашим ответом, если это возможно. Спасибо!

21 ответ

Решение

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 является базой, он может получить доступ к защищенным членам "other", которая также является базой.

C# принимает другую точку зрения. Это не позволяет "боковой" доступ, который делает VB. В нем говорится, что доступ к защищенным элементам может быть сделан через "this" или любой объект того же типа, что и класс, который содержит метод.

Поскольку "Foo" здесь определено в "Derived1", C# разрешает "Foo" получать доступ к элементам "Base" только из экземпляра "Derived1". "Другой" может быть чем-то, что не является "Derived1" (это может быть, например, "Derived2"), и поэтому он не разрешает доступ к "m_x".

VB.NET поддерживает фильтры исключений CIL, а C#:

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

Я удивлен, что небезопасный код C# еще не был упомянут. Это не разрешено в VB.NET.

Обрабатывает ключевые слова WithEvents для автоматического подключения EventHandlers.

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

Компилятор VB 9.0 автоматически переводит литеральный XML в синтаксис "функциональной конструкции". Компилятор C# не поддерживает этот красивый литеральный синтаксис XML.

В 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 позволяет не виртуальные вызовы методов виртуального экземпляра (call в IL), тогда как C# разрешает только виртуальные вызовы (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 года в журнале Visual Studio было несколько полезных статей.

В 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. Довольно часто я хочу определить интерфейс, который позволяет другому коду иметь возможность только читать свойство, но мне нужен открытый установщик в реализованном классе для использования персистором.

Одна из упущенных или просто неправильно понятых особенностей языка VB - это вызов функции, которая имеет ByRef параметр. Большинство языков поддерживают только один метод передачи параметров по ссылке: это сценарии, непосредственно поддерживаемые CLR.

CLR имеет множество ограничений на тип значений, которые он поддерживает для ByRef параметры и эти ограничения мешают цели VB быть гибким языком. Следовательно, компилятор идет на все, чтобы быть гибким и поддерживать несколько путей ByRef прохождение, намного больше, чем изначально позволяет CLR.

C# 4 теперь поддерживает две версии передачи ссылок. В дополнение к тому, доступному с 1.0 ref модификатор теперь необязателен при выполнении вызова взаимодействия с COM-объектом.

Индексированные свойства разрешены в 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):

"Особенности" языка VB не поддерживаются в C#:

  • Необязательные параметры
  • Позднее связывание
  • Нечувствительность к регистру

Я уверен, что есть больше. Ваш вопрос может получить лучшие ответы, если вы попросите конкретные примеры того, где каждый язык превосходит. В настоящее время VB лучше, чем C#, при взаимодействии с COM. Это связано с тем, что COM намного меньше головной боли, когда доступны необязательные параметры и когда вам не нужно привязываться к (часто неизвестному типу) во время компиляции.

C#, с другой стороны, предпочтительнее для многих при написании сложной логики из-за ее безопасности типов (в которой вы не можете обойти статическую типизацию) и ее краткости.

В конце концов, языки в основном эквивалентны, так как они различаются только по краям. Функционально они одинаково способны.

РЕДАКТИРОВАТЬ

Чтобы было ясно, я не подразумеваю, что VB не позволяет статическую типизацию... просто, что C# еще не позволяет вам обойти статическую типизацию. Это делает C# более привлекательным кандидатом для определенных типов архитектур. В спецификации языка 4.0 C# вы можете обойти статическую типизацию, но вы делаете это, определяя блок динамического кода, а не объявляя весь файл "не строгим", что делает его более осознанным и целенаправленным.

Один из моих любимых (и обломов)

В VB.Net вы можете использовать оператор switch/case следующим образом:

Select Case True

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

End Select

который позволяет вам оценивать некоторые сложные вычисления с помощью переключателя вместо множества блоков if/else. Вы не можете сделать это в C#.

VB имеет необязательные параметры для функций.

C# получит их только с C# 4.0

Ключевое слово volatile доступно только в C# http://www.devcity.net/Articles/160/5/article.aspx

Новые autoperperties в C# еще не были сделаны для VB.NET.

Точка с запятой, которая заканчивается каждой строкой в ​​C#, запрещена в VB, и это всегда вызывает у меня улыбку, когда я пытаюсь вернуться к VB.Net...

Как отметил Крис Данауэй, в VB.NET есть Модули, которые позволяют вам определять функции и данные.

VB.NET имеет синтаксис VB6 для связи с методами в DLL. Например:

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

(Хотя это фактическое заявление, возможно, должно быть маршалом)


В C# вы должны назначить свою переменную, прежде чем сможете ее использовать. Я думаю, что вы можете отключить это, но это поведение по умолчанию.

Так что-то вроде этого:

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

Не допускается, но VB эквивалент будет.

Глобальные переменные не существуют в C#, я думаю

True в VB.Net при преобразовании в целое число преобразуется в -1, а в C# - в 1.

Кроме того, ключевое слово NOT в VB.Net действительно является побитовым НЕ (как в C# '~') и не является логическим НЕ (C# '!').

В то время как для операторов И и ИЛИ, VB.Net уже имеет логические операторы AndAlso и OrElse, которые являются истинными логическими операторами и коротким замыканием, тем не менее, нет логического НЕ.

Это особенно важно при работе с Win32 API, в котором НЕ делается результат, предполагая, что если результат равен True, то NOT отрицает его, это неправильно, поскольку в C true == 1 и, следовательно, побитовое NOT на 1 также истинное значение (и это, вероятно, причина, по которой в VB true == -1, так как это единственное значение, для которого побитовое НЕ приведет к 0)

Другие вопросы по тегам