Неявно типизированные массивы

В С# 3.0 появился сокращенный способ инициализации массивов, когда конкретный тип массива может быть выведен во время выполнения. Взглянем на новый синтаксис на примере следующего фрагмента кода:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using System;
public class EntryPoint
{
static void Main()  {
// Традиционный массив
int[] conventionalArray = new int[] { 1, 2, 3 };
// Неявно типизированный массив
var implicitlyTypedArray = new []  { 4, 5, 6 };
Console.WriteLine( implicitlyTypedArray.GetType () );
// Массив double
var someNumbers = new []  { 3.1415, 1, 6 };
Console.WriteLine ( someNumbers.GetType () );
//He скомпилируется!
// var someStrings = new []  { "int",
// someNumbers.GetType()  };
}

Здесь для первой переменной массива по имени conventionalArray используется один из вариантов традиционного синтаксиса объявления и инициализации массива. Однако для следующей переменной —

1
implicitlyTypedArray

— применяется новый сокращенный синтаксис, лишенный информации о типе.

Вместо указания компилятору информации о типе ему просто предоставляется возможность догадаться, что каждый элемент в массиве будет иметь тип int.

Чтобы еще больше сэкономить на клавиатурном вводе,

1
implicitlyTypedArray

объявляется как неявно типизированная локальная переменная. Выполнив этот код, вы обнаружите, что вызов метода WriteLine, следующий за ней, показывает, что неявно типизированная переменная имеет тип

1
System.Int32[]

. Фактически, ту же строку кода можно было бы записать следующим образом:

1
int[] implicitlyTypedArray = new []  { 4, 5, 6 };

Однако, поскольку компилятору уже предоставлена возможность догадаться о типе элементов массива, можно позволить ему вывести весь тип массива, особенно если переменная остается локальной по отношению к контексту метода. Но что случится, если объявить массив, используя множество типов в списке инициализации?

Когда компилятор встречает множество типов внутри списка инициализации неявно типизированного массива, он определяет тип, к которому могут быть неявно приведены все элементы. И, конечно, для практических целей любой тип экземпляра может быть преобразован в собственный тип. Поэтому в объявлении экземпляра

1
someNumbers

в данном примере компилятор определит, что все типы внутри скобок являются преобразуемыми к

1
System.Double

.

Не удивительно, что следующий вызов метода

1
WriteLine

подтверждает это. Но что, если типы элементов не могут быть неявно преобразованы в один общий тип?

Когда компилятор не может найти подходящий общий тип, к которому можно преобразовать все элементы массива, он выдает ошибку CS0826:

No best type found for implicitly typed array
He найдено подходящего типа для неявно типизированного массива

Если удалить комментарий со строки, где объявляется переменная

1
some Strings

, именно такое предупреждение и сгенерируется, поскольку экземпляры

1
System.Туре

не могут быть неявно преобразованы к System.String.

Все объекты в .NET могут быть неявно преобразованы в System.Object; таким образом, может возникнуть вопрос, почему компилятор не принял решение использовать System.Object в качестве общего типа в предыдущем присваивании someStrings. Причина в том, что компилятор может применять только те типы, которые присутствуют в выражении неявно типизированного массива. Поскольку System.Object не входит в их число, он во внимание не принимается.

А что произойдет, если объявить массив с двумя элементами, и оба типа окажутся преобразуемыми друг к другу? Такая ситуация случается очень редко и обычно является следствием наличия двух пользовательских типов, у которых определены операции неявного преобразования друг в друга.

Чтобы посмотреть, что случится, так было и сделано. При попытке объявить неявно типизированный массив с элементами каждого из типов возникла ошибка компиляции CS0826, как и следовало ожидать.

Возможно, вы уже думаете о множестве полезных применений для неявно типизированных массивов. Однако в большинстве случаев они просто экономят клавиатурный набор.

Это удобно, когда массив содержит закрытые обобщенные типы, которые требуют значительного клавиатурного набора для ввода их типа.

Потому в данном отношении неявно типизированные массивы позволяют написать более читабельный код. Но в других случаях они, наоборот, могут затруднить понимание кода для инженеров службы сопровождения, если знание типа массива в точке его объявления существенно для понимания работы кода.

Поскольку неявно типизированные массивы в действительности являются неявно типизированными локальными переменными, то если только метод, который вы читаете, не слишком сложный и большой, у вас не должно быть проблем в определении действительного типа такой переменной.

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

С учетом всего сказанного, неявно типизированные массивы отлично подходят для создания экземпляров n-кратных элементов. Например, в следующем фрагменте кода демонстрируется сокращенный способ объявления матрицы целых чисел:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
using System;
public class EntryPoint {
static void Main()  {
var threeByThree = new []  {
new []  { 1, 2, 3 },
new []  { 4, 5, 6 },
new []  { 7, 8, 9 }
};
foreach ( var i in threeByThree )  {
foreach ( var j ini )  {
Console.Write ( "{0}, j );
}
Console.Write ( "\n" );
}

Вы можете следить за любыми ответами на эту запись через RSS 2.0 ленту. Вы можете оставить ответ, или trackback с вашего собственного сайта.

Оставьте отзыв

XHTML: Вы можете использовать следующие теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

 
Rambler's Top100