Что разрешено в 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
Точка с запятой, которая заканчивается каждой строкой в 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 эквивалент будет.
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)