С момента появления языка Visual Basic в 1991 году он стал высокоэффективным инструментом для создания приложений. Почти 20 лет спустя он продолжает обеспечивать простую интеграцию с Microsoft .NET Framework, позволяя разработчикам писать приложения, которые охватывают настольные компьютеры, телефоны, браузеры и даже облако.
В этом месяце Microsoft выпустит Visual Studio 2010, которая включает Visual Basic версии 10 (иногда называемую VB 2010 или VB10). Этот выпуск является самым мощным и включает в себя множество функций, позволяющих экономить время, помогая разработчикам делать больше с меньшим количеством строк кода. Здесь вам будет предоставлен весь необходимый контент для полного понимания и использования Visual Basic в Visual Studio 2010.
коэволюция
Раньше Visual Basic и C# разрабатывались отдельными командами, в результате чего функции часто появлялись сначала на одном языке, а затем на другом. Например, в C# есть автоматически реализуемые свойства и инициализаторы коллекций, недоступные в Visual Basic, а в Visual Basic есть такие функции, как позднее связывание и необязательные параметры, недоступные в C#. Но каждый раз, когда в языке появляется новая функция, многие клиенты просят добавить эту функцию и в другой язык.
Чтобы удовлетворить эту потребность, Microsoft объединила команды Visual Basic и C# для реализации стратегии совместной эволюции. Целью является содействие общему развитию этих языков. Когда основная функция представлена на одном языке, она появляется и на другом языке. Это не значит, что каждая функция будет присутствовать в обоих языках и работать одинаково; на самом деле у каждого языка есть своя история, душа и ощущение – и важно сохранить эти характеристики.
В .NET Framework 4 Visual Basic и C# сделали большой шаг к этой цели, вобрав в себя многие существующие функции друг друга. Однако коэволюция влияет не только на прежнюю функциональность; это также стратегия будущего развития этих языков. В этом духе .NET Framework 4 представляет новые мощные функции на обоих языках, такие как среда выполнения динамического языка, встроенные типы взаимодействия и универсальная вариативность, что позволяет разработчикам Visual Basic и C# в полной мере использовать преимущества .NET Framework.
Что нового в Visual Basic 2010
Новые возможности Visual Basic 2010 призваны помочь вам добиться большего с меньшим количеством строк кода. Наша группа разработчиков Visual Basic внимательно изучила места, где разработчикам обычно приходится писать много утомительного шаблонного кода, и нашла способы позволить компилятору выполнять всю работу вместо этого. Конечно, это общий вид, теперь давайте более подробно рассмотрим каждую особенность.
Символ неявного продолжения строки
Visual Basic — это строко-ориентированный язык, в котором для повышения читабельности используется понятный синтаксис, аналогичный английскому. Но это часто приводит к тому, что код достигает предела в 80 символов в строке, что вынуждает разработчиков много прокручивать. Вы можете использовать символ подчеркивания, чтобы сообщить компилятору, что обработка следующей строки должна продолжаться как текущая строка (то есть рассматривать несколько физических строк как одну логическую строку). Но необходимость многократного ввода символа подчеркивания раздражала, и на самом деле в течение многих лет самой популярной функцией было исправление этой проблемы компилятором.
В Visual Basic 2010 эту проблему может решить компилятор. Теперь компилятор знает, какие лексемы (например, запятые, круглые скобки и операторы) обычно появляются перед символами продолжения строки, и вставляет символы, поэтому разработчикам больше не нужно вставлять символы. Например, совершенно нелогично заканчивать оператор Visual Basic запятой; компилятор знает об этом, поэтому, когда он видит поток токенов, таких как {comma, enter}, он предполагает наличие символа продолжения строки, как показано на рисунке. Показан пример 1.
Рисунок 1. Вывод символов продолжения строки
<Extension()>
Функция FilterByCountry(
Клиенты ByVal как IEnumerable (клиента),
Страна по значению как строка) Как IEnumerable (клиента)
Тусклый запрос=
От клиентов
Где c.Country = страна
Выберите <Клиент>
<%=
c.Имя и
, &
в.Страна
%>
</Клиент>
Обратный запрос
Конечная функция
В Visual Basic 2008 код, показанный на рисунке 1, потребует 9 символов подчеркивания. Однако в каждом из следующих случаев компилятор определяет, когда символ подчеркивания необходим, и позволяет его игнорировать:
После атрибута <Extension()>
после ((левая скобка) в объявлении метода
после , (запятой) первого параметра
перед ) (правая скобка) в объявлении метода
после = (знак равенства)
после <%= (открывающий тег встроенного выражения)
После каждого амперсанда (амперсанда) в XML-тексте
перед %> (конечный тег встроенного выражения)
Эта новая функция компилятора особенно полезна для сигнатур методов, которые в показанном примере также будут работать нормально для длиннее 80 символов (если каждая часть находится в одной строке). На рисунке 2 вы увидите все комбинации тегов и позиций, для которых неявно используются символы продолжения строки.
Рис. 2. Символ продолжения строки неявно
отметка | До | после |
, (запятая), . (точка), > (атрибут), ( { (левая скобка), <%= (начальный тег встроенного выражения (текст XML)) | Х | |
), }, ] (правая скобка), %> (конечный тег встроенного выражения) | Х | |
Все ключевые слова LINQ: Агрегировать, Отличаться, От, Группировать, Присоединиться к группе, Присоединиться, Разрешить, Упорядочить по, Выбрать, Пропустить, Пропустить пока, Взять, Взять пока, Где, В, В, Вкл, По возрастанию, По убыванию | Х | Х |
Оператор: +, -,*,/,/,^,>>,<<,Mod,&,+=,-=,*=,/=,/=,^=,>>=,<<=, & =, <, <=, >, >=, <>, Is, IsNot, Like, And, Or, Xor, AndAlso, OrElse | Х | |
С (в инициализаторе объекта) | Х |
Как видите, в языке более 60 мест, где символ подчеркивания не требуется. (На самом деле ни один из примеров кода в этой статье не требует символов продолжения строки.) Конечно, вы все равно можете использовать символ подчеркивания, поэтому код из предыдущих версий Visual Basic по-прежнему будет компилироваться должным образом.
ЗаявлениеЛямбда
Термин «лямбда» на первый взгляд может показаться пугающим, но лямбда — это просто функция, определенная внутри другой функции. В Visual Basic 2008 появились лямбда-выражения с ключевым словом Function:
Dim customers As Customer() = ...
Array.FindAll(клиенты, Функция(c) c.Country = Канада)
Лямбда-выражения позволяют выражать логику локально детальным и компактным образом без необходимости разделения ее на несколько методов. Например, вот представление предыдущего кода в Visual Basic 2005 (который не поддерживает лямбда-выражения):
Dim query = Array.FindAll(customers, AddressOf Filter)
...
Функция Filter (ByVal c Как клиент) Как логическое значение
Возврат c.Страна = Канада.
Конечная функция
К сожалению, лямбда-выражения Visual Basic 2008 требуют, чтобы выражение возвращало значение, поэтому следующий код:
Array.ForEach(customers, Function(c) Console.WriteLine(c.Country))
Приведет к следующей ситуации:
'Compile error: Expression does not produce a value.
Console.WriteLine — это процедура Sub (void в C#), поэтому она не возвращает значение, поэтому компилятор генерирует ошибку. Чтобы справиться с этой ситуацией, в Visual Basic 2010 появилась поддержка лямбда-выражений операторов, которые содержат один или несколько операторов:
Array.ForEach(customers, Sub(c) Console.WriteLine(c.Country))
Поскольку Console.WriteLine не возвращает значение, мы можем просто создать лямбду Sub вместо лямбды Function. Вот еще один пример использования нескольких операторов:
Array.ForEach(customers, Sub(c)
Console.WriteLine(Название страны:)
Console.WriteLine(c.Country)
Конец субтитра)
При запуске этого кода он печатает две строки для каждого клиента. Также обратите внимание: если вы наведете курсор на c во время кодирования, вы увидите, что компилятор определит тип как Customer (также допустимо ввести c As Customer для явного объявления типа). Динамическое написание обработчиков событий — еще одно замечательное применение лямбда-выражений:
AddHandler b.Click, Sub(sender As Object, e As EventArgs)
MsgBox (нажата кнопка)
'вставьте сюда более сложную логику
Конец субтитра
И действительно, вы можете использовать лямбда-выражения операторов с помощью функции, представленной в Visual Basic 2008: свободного делегирования. (Вы можете использовать делегаты — типобезопасные указатели функций — для одновременного выполнения нескольких функций.) Эта комбинация приводит к гораздо более простой сигнатуре:
AddHandler b.Click, Sub()
MsgBox (нажата кнопка)
'вставьте сюда более сложную логику
Конец субтитра
Свобода делегирования позволяет полностью игнорировать параметры в обработчиках событий — это приятное преимущество, поскольку они вообще не используются и навязчивы только визуально.
В дополнение к однострочным лямбда-выражениям Sub и многострочным лямбда-выражениям Sub, которые мы видели до сих пор, Visual Basic 2010 также поддерживает многострочные лямбды-функции:
Dim query = customers.Where(Function(c)
'Вернуть только тех клиентов, которые не были сохранены
'вставьте сюда более сложную логику
Возврат c.ID = -1
Конечная функция)
Еще один интересный аспект лямбда-выражений операторов — то, как они пересекаются с анонимными делегатами, представленными в Visual Basic 2008. Люди часто путают эти делегаты с анонимными методами C#, хотя они не совсем одно и то же. Анонимное делегирование происходит, когда компилятор Visual Basic определяет тип делегата на основе сигнатуры лямбда-метода:
Dim method = Function(product As String)
Если продукт = Бумага Тогда
Возврат 4,5-дюймовых единиц на складе
Еще
Верните 10 '10 всего остального
Конец, если
Конечная функция
MsgBox(метод(Бумага))
Если вы запустите этот код, вы увидите значение 4,5, отображаемое в окне сообщения. Кроме того, если вы наведете курсор на метод, вы увидите текст Dim Method As <Function(String) As Double>. Поскольку мы не предоставили фактический тип делегата, компилятор автоматически сгенерирует его следующим образом:
Delegate Function $compilerGeneratedName$(product As String) As Double
Это называется анонимным делегатом, поскольку он будет отображаться только в коде, сгенерированном компилятором, а не в написанном коде. Обратите внимание: когда на самом деле не предусмотрено предложение As для указания типа возвращаемого значения лямбды, компилятор определяет тип возвращаемого значения как Double. Компилятор просмотрит все операторы возврата в лямбда-выражении и определит типы Double (4.5) и Integer (10):
'Notice the As Single
Метод Dim = Функция (продукт как строка) как одиночный
Если продукт = Бумага Тогда
Возврат 4,5-дюймовых единиц на складе
Еще
Верните 10 '10 всего остального
Конец, если
Конечная функция
Затем он запускает алгоритм базового типа и определяет, что он может безопасно преобразовать 10 в число Double, но не может безопасно преобразовать 4,5 в целое число, поэтому Double является лучшим выбором.
Вы также можете явно контролировать тип возвращаемого значения, и в этом случае компилятор не будет пытаться определить тип. Очень часто лямбда-выражение присваивается переменной с явным типом делегата, вместо того, чтобы полагаться на то, что компилятор определит тип делегата:
Dim method As Func(Of String, Single) =
Функция (продукт)
Если продукт = Бумага Тогда
Возврат 4,5-дюймовых единиц на складе
Еще
Верните 10 '10 всего остального
Конец, если
Конечная функция
Поскольку указан явный целевой тип, нет необходимости объявлять As String или As Single, компилятор может сделать вывод о его существовании на основе типа делегата в левой части оператора. Поэтому, если вы наведете курсор на продукт, вы увидите, что предполагаемый тип — String. Вам больше не нужно указывать «Как одиночный», поскольку тип делегата уже предоставляет эту информацию. В предыдущем примере подпись делегата Func (входящего в состав .NET Framework) выглядит следующим образом:
Delegate Function Func(Of T, R)(ByVal param As T) As R
Есть одно небольшое исключение, как мы увидим позже в разделе «Общая дисперсия».
Автоматически реализуемые свойства
В Visual Basic свойства — это члены класса, которые раскрывают состояние объекта внешнему миру. Типичное объявление свойства выглядит следующим образом:
Private _Country As String
Страна свойства в виде строки
Получать
Возврат_Страна
Конец Получить
Set (значение ByVal как строка)
_Страна = значение
Конечный набор
Конечная собственность
На самом деле очень простая концепция с 10 строками кода. Поскольку типичный объект часто имеет десятки свойств, в определение класса приходится включать много шаблонного кода. Чтобы упростить такие задачи, в Visual Basic 2010 представлены автоматически реализуемые свойства, которые позволяют определять простые свойства с помощью всего одной строки кода:
Property Country As String
В этом случае компилятор продолжит работу и автоматически сгенерирует геттеры, сеттеры и вспомогательные поля. Имя поддерживаемого поля всегда представляет собой имя атрибута, которому предшествует символ подчеркивания: в этом примере _Country. Это соглашение об именах обеспечивает совместимость двоичной сериализации при изменении автоматически реализуемых свойств на обычные свойства. Двоичная сериализация будет продолжать работать, пока имена вспомогательных полей остаются прежними.
Одна из приятных вещей, которые вы можете сделать с автоматически реализуемыми свойствами, — это указать инициализатор, который устанавливает значение свойства по умолчанию при запуске конструктора. Например, в распространенном сценарии с классами сущностей первичному ключу присваивается значение, например -1, чтобы указать, что он находится в несохраненном состоянии. Код будет выглядеть следующим образом:
Property ID As Integer = -1
При запуске конструктора резервному полю (_ID) автоматически присваивается значение -1. Синтаксис инициализатора также работает для ссылочных типов:
Property OrderList As List(Of Order) = New List(Of Order)
Поскольку вам не нужно вводить имя типа дважды, предыдущая строка кода может не иметь очевидных характеристик Visual Basic. Хорошей новостью является то, что для объявлений обычных переменных существует более короткий синтаксис, соответствующий синтаксису, разрешенному Visual Basic:
Property OrderList As New List(Of Order)
Вы даже можете использовать этот синтаксис с инициализатором объекта, чтобы разрешить установку других свойств:
Property OrderList As New List(Of Order) With {.Capacity = 100}
Очевидно, что для более сложных свойств по-прежнему необходим расширенный синтаксис. Вы по-прежнему можете ввести Property{Tab}, чтобы активировать старый фрагмент свойства. Альтернативно, после ввода первой строки свойства вы можете просто ввести Get{Enter}, и IDE сгенерирует свойство старого стиля:
Property Name As String
Получать
Конец Получить
Set (значение ByVal как строка)
Конечный набор
Конечная собственность
Обычно обнаруживается: синтаксис нового свойства почти идентичен синтаксису общедоступных полей, так почему бы не использовать вместо него общедоступные поля? Есть несколько причин:
Большая часть инфраструктуры привязки данных .NET работает с использованием свойств, а не полей.
Интерфейс не может обеспечить наличие поля; он может обеспечить наличие атрибута.
Свойства обеспечивают долгосрочную гибкость для изменения бизнес-правил. Например, предположим, что кто-то вводит правило, согласно которому телефонные номера должны состоять из 10 цифр. Эту проверку невозможно выполнить, если она назначена общедоступному полю. Изменение общедоступных полей на свойства — это радикальное изменение для таких сценариев, как двоичная сериализация и отражение.
Инициализатор коллекции
Обычной практикой .NET является создание экземпляра коллекции, а затем ее заполнение путем вызова метода Add один раз для каждого элемента:
Dim digits As New List(Of Integer)
цифры.Добавить(0)
цифры.Добавить(1)
цифры.Добавить(2)
цифры.Добавить(3)
цифры.Добавить(4)
цифры.Добавить(5)
цифры.Добавить(6)
цифры.Добавить(7)
цифры.Добавить(8)
цифры.Добавить(9)
Но для фундаментально простой концепции требуется много синтаксических накладных расходов. В Visual Basic 2010 появились инициализаторы коллекций, упрощающие создание экземпляров коллекций. Для этого кода:
Dim digits = New List(Of Integer) From {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}
Компилятор автоматически сгенерирует все вызовы метода Add. Вы также можете использовать функцию синтаксиса Visual Basic As New:
Dim digits As New List(Of Integer) From {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}
Обратите внимание, что в команде Visual Basic мы всегда рекомендуем использовать второй синтаксис (как новый) вместо первого, поскольку он делает код более устойчивым к изменениям в параметре Option Infer.
Вы можете использовать инициализатор коллекции для любого типа, который соответствует следующим требованиям:
Перебирать тип можно с помощью оператора For Each — то есть тип реализует IEnumerable. (Более точное/подробное определение типов коллекций см. в разделе 10.9.3 спецификации языка Visual Basic по адресу msdn.microsoft.com/library/aa711986(VS.71).aspx).
Тип имеет доступный (но не обязательно общедоступный) конструктор без параметров.
Тип имеет доступный (но не обязательно общедоступный) экземпляр или метод расширения с именем Add.
Это означает, что вы также можете использовать инициализаторы коллекций для более сложных типов, таких как словари:
Dim lookupTable As New Dictionary(Of Integer, String) From
{{1, Один},
{2, Два},
{3, Три},
{4, Четыре}}
(Обратите внимание, что хотя этот оператор занимает пять строк, в нем нет символов подчеркивания.) В этом случае компилятор сгенерирует код, эквивалентный старому способу инициализации словаря:
Dim lookupTable As New Dictionary(Of Integer, String)
LookupTable.Add(1, Один)
LookupTable.Add(2, Два)
LookupTable.Add(3, Три)
LookupTable.Add(4, Четыре)
Компилятор вызывает метод Add с двумя параметрами вместо одного. Он знает, что это нужно сделать, поскольку значение, передаваемое в инициализатор коллекции, находится внутри вложенных фигурных скобок, например: {{1, One}, {2, Two}, …}. Для каждого набора вложенных фигурных скобок компилятор пытается передать эти параметры совместимому методу Add.
Также можно предоставить собственную реализацию Add, используя методы расширения:
<Extension()>
Sub Add (источник ByVal как IList (клиента),
ByVal идентификатор как целое число,
ByVal name As String,
ByVal город As String)
source.Add(Новый клиент с
{
.ID = идентификатор,
.Имя = имя,
.Город = город
})
Конец субтитра
(Посмотрите на все эти недостающие символы подчеркивания!) Этот метод расширяет любой тип, реализующий IList(Of Customer), который затем позволяет вам использовать новый синтаксис инициализатора коллекции, например:
Dim list = New List(Of Customer) From
{
{1, Джон, Редмонд},
{2, Боб, Сиэтл},
{3, Салли, Торонто}
}
(Добавьте в список трех клиентов). Вы также можете использовать инициализаторы коллекций с автоматически реализуемыми свойствами:
Property States As New List(Of String) From {AL, AK, AR, AZ, ...}
литерал массива
Помимо более мощных способов работы с типами коллекций, Visual Basic 2010 также предоставляет некоторые мощные улучшения для работы с массивами. Предположим следующий код (отлично работает в старых версиях):
Dim numbers As Integer() = New Integer() {1, 2, 3, 4, 5}
Глядя на элементы этого массива, становится очевидным, что каждый элемент является целым числом, поэтому необходимость дважды распечатывать целое число в этой строке на самом деле не добавляет никакой ценности. Литералы массива позволяют создавать массив, помещая все элементы массива в фигурные скобки и позволяя компилятору автоматически определять типы:
Dim numbers = {1, 2, 3, 4, 5}
Тип чисел — не Object, а Integer() (пока включен Option Infer), причина в том, что литерал массива теперь представляет сам себя и имеет свой собственный тип. Возьмем более сложный пример:
Dim numbers = {1, 2, 3, 4, 5.555}
В этом случае тип чисел будет определяться как Double(). Компилятор определяет тип, проверяя каждый элемент массива и вычисляя базовый тип, используя тот же алгоритм, который обсуждался ранее для определения типа возвращаемого значения лямбда-выражения. Что произойдет, если базового типа нет? Например, как показано в следующем коде:
Dim numbers = {1, 2, 3, 4, 5}
В этом случае преобразование целого числа в строку уменьшит диапазон преобразования (то есть во время выполнения может произойти потеря данных), и аналогичным образом преобразование строки в целое число также уменьшит диапазон преобразования. Единственный безопасный тип, который можно выбрать, — это Object() (компилятор выдаст ошибку, если включен Option Strict).
Литералы массива могут быть вложены в многомерные или зубчатые массивы:
'2-dimensional array
Тусклая матрица = {{1, 0}, {0, 1}}
'зубчатый массив - круглые скобки заставляют сначала оценивать внутренний массив
Тусклые зубцы = { ({1, 0}), ({0, 1}) }
динамическая языковая среда выполнения
Хотя Visual Basic по своей природе является статическим языком, он всегда имел очень мощные динамические функции, такие как позднее связывание. Visual Studio 2010 поставляется с новой платформой под названием Dynamic Language Runtime (DLR), которая упрощает создание динамических языков и взаимодействие между ними. Visual Basic 2010 был обновлен для полной поддержки DLR в его поздних версиях связующих, что позволяет разработчикам использовать библиотеки и платформы, разработанные на других языках (например, IronPython/IronRuby).
Одна из замечательных особенностей этой функции заключается в том, что синтаксически ничего не изменилось (фактически, в компиляторе не было изменено ни одной строки кода для поддержки этой функции). Разработчики по-прежнему могут выполнять операции позднего связывания, как и в предыдущих версиях Visual Basic. Что изменилось, так это код среды выполнения Visual Basic (Microsoft.VisualBasic.dll), который теперь распознает интерфейс IDynamicMetaObjectProvider, предоставляемый DLR. Если объект реализует этот интерфейс, среда выполнения Visual Basic создает DLR CallSite и позволяет объекту и языку, который его предоставляет, внедрить в операцию свою собственную семантику.
Например, стандартная библиотека Python содержит файл с именем random.py, в котором есть метод shuffle, который можно использовать для случайного переупорядочивания элементов в массиве. Вызов этого метода прост:
Dim python As ScriptRuntime = Python.CreateRuntime()
Тусклый случайный объект As Object = python.UseFile(random.py)
Тусклые элементы = {1, 2, 3, 4, 5, 6, 7}
Random.shuffle(предметы)
Во время выполнения Visual Basic видит, что объект реализует IDynamicMetaObjectProvider, и поэтому передает управление DLR, который затем взаимодействует с Python и выполняет метод (передавая массив, определенный в Visual Basic, в качестве параметра методу).
Это пример вызова API с поддержкой DLR, но разработчики также могут создавать свои собственные API, использующие эту функциональность. Ключевым моментом является реализация интерфейса IDynamicMetaObjectProvider, и в этом случае компиляторы Visual Basic и C# будут распознавать объекты со специальной динамической семантикой. Пожалуйста, не реализуйте этот интерфейс вручную, его проще наследовать от класса System.Dynamic.DynamicObject (который уже реализует этот интерфейс) и переопределить лишь несколько методов. На рис. 3 показан полный пример создания пользовательского динамического объекта (пакета свойств, который создает свойства «на лету») и использования обычного позднего связывания Visual Basic для вызова объекта. (Для получения дополнительной информации об использовании DynamicObject прочитайте прекрасную статью Дуга Ротхауса по адресу blogs.msdn.com/vbteam/archive/2010/01/20/fun-with-dynamic-objects-doug-rothaus.aspx.)
Рис. 3. Создайте собственный динамический объект и вызовите его с помощью позднего связывания Visual Basic.
Imports System.Dynamic
Модуль Модуль1
Подглавная()
Dim p As Object = Новый PropertyBag
п.Один = 1
п.Два = 2
п.Три = 3
Console.WriteLine(p.One)
Console.WriteLine(стр.два)
Console.WriteLine(стр.три)
Конец субтитра
Класс PropertyBag: наследует DynamicObject
Частные значения как новый словарь (строка, целое число)
Публичная переопределяющая функция TrySetMember(
Связующее ByVal Как SetMemberBinder,
Значение ByVal Как объект) Как логическое значение
значения (связующее.Имя) = значение
Вернуть истину
Конечная функция
Публичная переопределяющая функция TryGetMember(
Связующее ByVal Как GetMemberBinder,
Результат по ссылке Как объект) Как логическое значение
Возвращаемые значения.TryGetValue(binder.Name, result)
Конечная функция
Конечный класс
Конечный модуль
общая дисперсия
Эта функция на первый взгляд действительно может показаться сложной (с такими терминами, как ковариация и контравариантность), но на самом деле она довольно проста. Если у вас есть объект типа IEnumerable(Of Apple) и вы хотите назначить его IEnumerable(Of Fruit), это должно быть законно, поскольку каждое яблоко является фруктом (принудительно наследованием). К сожалению, до Visual Basic 2010 универсальная вариативность не поддерживалась в компиляторе, хотя на самом деле она поддерживалась в среде CLR.
Давайте посмотрим на пример на рисунке 4. В Visual Basic 2008 код на рис. 4 выдаст ошибку компиляции в строке Dim EnableOnly (или, если Option Strict отключен, исключение времени выполнения). Обходной путь — вызвать метод расширения .Cast следующим образом:
'Old way, the call to Cast(Of Control) is no longer necessary in VB 2010
Dim EnableOnly = FilterEnabledOnly(buttons.Cast(Of Control))
В этом больше нет необходимости, поскольку в Visual Basic 2010 интерфейс IEnumerable помечен как ковариантный с помощью модификатора Out:
Interface IEnumerable(Of Out T)
...
Конечный интерфейс
Рисунок 4. Пример общей дисперсии
Option Strict On
Форма публичного класса1
Sub Form1_Load() обрабатывает MyBase.Load
Тусклые кнопки как новый список (кнопок) из
{
Новая кнопка с
{
.Name = бтнОк,
.Включено = Истина
},
Новая кнопка с
{
.Name = btnCancel,
.Включено = Ложь
}
}
Dim EnableOnly = FilterEnabledOnly(кнопки)
Конец субтитра
Функция FilterEnabledOnly(
Элементы управления ByVal как IEnumerable (Of Control)
) Как IEnumerable (управления)
Возврат из элементов управления c In
Где c.Enabled = True
Конечная функция
Конечный класс
Это означает, что универсальный параметр T теперь является переменной (то есть он пригоден для наследования), и компилятор будет гарантировать, что этот параметр будет использоваться только там, где тип поступает из интерфейса. Общие параметры также могут быть обратными переменными, то есть они используются только там, где они введены. На самом деле тип может иметь и то, и другое. Например, обсуждавшийся ранее делегат Func имеет как контравариантные параметры (для того, что передается), так и ковариантные параметры (для возвращаемого типа):
Delegate Function Func(Of In T, Out R)(ByVal param As T) As R
Вы можете использовать модификаторы In и Out в пользовательских интерфейсах и делегатах. Многие общие интерфейсы и делегаты в .NET Framework 4 помечены как переменные; распространенные примеры включают все делегаты Action/Func, IEnumerable(Of T), IComparer(Of T), IQueryable(Of T) и т. д.
Самое замечательное в общей дисперсии то, что об этой функции вообще не нужно беспокоиться: если она выполняет свою работу, вы ее никогда не заметите. Ситуации, которые когда-то приводили к ошибкам компилятора или требовали вызова .Cast(Of T), нормально работают в Visual Basic 2010.
Улучшенные дополнительные параметры
Необязательные параметры обеспечивают полезную функцию повышения эффективности, которая позволяет разработчикам создавать более гибкие методы и избегать загромождения класса множеством перегрузок методов. Раньше существовало небольшое ограничение: необязательные параметры не могли быть нулевыми (или даже относиться к какому-либо невнутреннему типу структуры). Visual Basic 2010 теперь позволяет определять необязательные параметры любого типа значения:
Sub DisplayOrder(ByVal customer As Customer,
ByVal orderID Как целое число,
Дополнительные единицы измерения ByVal. Как целое число = 0,
Необязательный ByVal backgroundColor As Color = Ничего)
Конец субтитра
В этом примере единицы имеют тип Nullable(Of Integer), а фоновый цвет — это тип структуры, не связанной с содержимым, но они по-прежнему используются в качестве необязательных параметров. Visual Basic 2010 также обеспечивает улучшенную поддержку универсальных необязательных параметров.
Встроенные типы взаимодействия
Распространенной слабостью приложений, выполняющих взаимодействие COM, является необходимость использования первичной сборки взаимодействия (PIA). PIA — это сборка .NET, которая действует как вызываемая оболочка среды выполнения (RCW) для COM-компонента и имеет уникальный идентификатор GUID, идентифицирующий ее. Сборка .NET взаимодействует с PIA, который затем выполняет необходимую маршалинг для перемещения данных между COM и .NET.
К сожалению, PIA могут усложнить развертывание, поскольку представляют собой дополнительные библиотеки DLL, которые необходимо развертывать на компьютерах конечных пользователей. Они также могут вызвать проблемы с управлением версиями — например, если вы хотите, чтобы ваше приложение работало как с Excel 2003, так и с Excel 2007, вам необходимо будет развернуть оба PIA вместе с вашим приложением.
Функция встроенного типа взаимодействия встраивается непосредственно в приложение, но только те типы и члены из PIA, которые абсолютно необходимы, поэтому нет необходимости развертывать PIA на компьютере конечного пользователя.
Чтобы включить эту функцию для существующего объекта (она включена по умолчанию для новых ссылок), выберите ссылку в обозревателе решений и измените параметр «Встроить типы взаимодействия» в окне «Свойства» (см. рис. 5). Альтернативно, при компиляции с помощью компилятора командной строки ming используйте ключ /l (или /link) вместо /r и /reference.
Рис. 5. Включение встроенных типов взаимодействия в обозревателе решений
После включения этой функции приложение больше не будет полагаться на PIA. Фактически, если вы откроете сборку в Reflector или ildasm, вы заметите, что на самом деле ссылки на PIA вообще нет.
Несколько целей
Самое приятное во всех функциях Visual Basic 2010 — это то, что их можно использовать даже в проектах, ориентированных на версии от .NET Framework 2.0 до .NET Framework 3.5. Это означает, что такие функции, как неявные символы продолжения строки, литералы массива, инициализаторы коллекций, лямбда-выражения операторов, автоматически реализуемые свойства и т. д., будут доступны в существующих проектах без необходимости перенацеливания .NET Framework 4.
Исключением являются встроенные типы взаимодействия, которые основаны на типах, доступных только в .NET Framework 4, поэтому, если вы ориентируетесь на версии .NET Framework 2,0–3,5, вы не сможете использовать эту функцию; Кроме того, типы, помеченные как переменные, помечаются только так, как они были в .NET Framework 4, поэтому в предыдущем примере, если вы ориентируетесь на версии 2.0–3.5, вам все равно придется вызывать .Cast(Of T). Однако если вы ориентируетесь на эти более ранние версии, вы можете создавать свои собственные типы переменных (используя модификаторы In/Out).
Чтобы изменить текущую целевую платформу вашего приложения, дважды щелкните «Мои проекты», перейдите на вкладку «Компиляция», нажмите «Дополнительные параметры компиляции», а затем выберите вариант из поля со списком внизу.
На самом деле не существует переключателя командной строки ming, позволяющего включить эту функцию при компиляции из командной строки ming. По сути, компилятор смотрит, какая сборка предоставляет определение System.Object (обычно mscorlib) и для какой платформы предназначена сборка, а затем отмечает это значение в выходной сборке. (Компилятор использует тот же механизм при создании сборок Silverlight.) При использовании IDE все это происходит прозрачно, поэтому вам обычно не о чем беспокоиться.
Добро пожаловать, попробуйте
Как видите, Visual Basic 2010 имеет множество мощных функций, которые позволяют вам работать более продуктивно, написав меньше строк кода и позволяя компилятору выполнять большую часть работы. В этой статье я обсудил только возможности языка, но в Visual Basic 2010 IDE имеется бесчисленное множество замечательных улучшений. Некоторые улучшения перечислены ниже:
Перейдите к
Выделить цитаты
созданный в результате использования
Улучшенный IntelliSense (сопоставление подстрок, поиск в верблюжьем регистре, шаблоны предложений — полезно сначала протестировать ваш стиль разработки)
Поддержка нескольких мониторов
Увеличить
Команда Visual Basic с нетерпением ждет ваших отзывов о наших усилиях по улучшению Visual Basic, поэтому присылайте нам свои комментарии и вопросы на Microsoft Connect. Чтобы узнать больше о языке и функциях IDE, ознакомьтесь с материалами на сайте msdn.com/vbasic, которые включают статьи, примеры и обучающие видеоролики. Конечно, лучший способ научиться — это вникать в продукт и использовать его, поэтому пришло время его установить и опробовать.