Почему компилятор не конвертирует var [] в object [] в c #? - PullRequest
32 голосов
/ 17 января 2012

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

var x = new int[] { 1, 2, 3 };   //Fine, x is int[]
var x = new [] { 1, 2, 3 };      //Fine, x is int[]

Но почемуя делаю это с разными типами?Почему компилятор не преобразует мою переменную в тип object ?

var x = new object[] { 1, "df", 5 };   //Fine, x is object[]
var x = new [] { 1, "df", 5 };         //Error! "No best type found for implicity-typed-array"

EDIT:

Спасибо за все ваши ответы.Но мне все еще интересно, каковы плюсы и минусы для создания всех выражений, которые компилятор не может преобразовать в тип object?(Поскольку я использую нотацию var, что означает, что это не может быть какой-либо тип. Я так понимаю.) Почему компилятор не находит ближайший тип членов массива, поднимаясь по дереву наследования?

Ответы [ 2 ]

38 голосов
/ 17 января 2012

Обозначение new [] предназначено для сохранения возможности вводить явный тип членов массива (или для создания массивов, где его элементы имеют анонимный тип), но вывод типа ограничен тем, что все элементы должны совместно использовать того же типа или быть неявно конвертируемым в общий тип, используемый по крайней мере одним членом. См. Спецификацию C #, раздел 7.6.10.4:

.

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

Ниже приведены примеры неявно типизированных выражений создания массива:

var a = new[] { 1, 10, 100, 1000 };                       // int[]
var b = new[] { 1, 1.5, 2, 2.5 };                         // double[]
var c = new[,] { { "hello", null }, { "world", "!" } };   // string[,]
var d = new[] { 1, "one", 2, "two" };                     // Error

Последнее выражение вызывает ошибку во время компиляции, потому что ни int, ни string не являются неявно конвертируемыми для другого, и поэтому нет лучшего общего типа. В этом случае необходимо использовать явно выраженное выражение для создания массива, например, указав тип object[]. В качестве альтернативы, один из элементов может быть приведен к общему базовому типу, который затем станет типом предполагаемого элемента.

Ключевым моментом здесь является то, что «наилучшим общим типом» может быть только один из уже существующих типов. Как отметил Damien_The_Unbeliever в комментарии: «Поскольку мистер Липперт любит указывать на вывод, всякий раз, когда он ищет лучший общий тип, он возвращает только один из типов, который уже есть. настоящее - оно не идет на охоту за самым производным общим предком ». .

То, что каждый массив может быть object [], не означает, что он должен. С точки зрения компилятора, это было бы тривиальным выбором в крайнем случае, но, как мне кажется, очень нелогичным для разработчика.

18 голосов
/ 17 января 2012

Чтобы расширить ответ Джои, рассмотрим следующий пример:

interface IFoo { }
interface IBar { }

class A : IFoo, IBar { }
class B : IFoo, IBar { }

var array = new [] { new A(), new B() };

Оба класса реализуют оба интерфейса (и также являются производными от object), поэтому какой тип следует выводить для array?


Чтобы ответить на ваш комментарий, рассмотрим случай, когда A и B совместно используют только один интерфейс:

interface IFoo { }

class A : IFoo { }
class B : IFoo { }

var array = new [] { new A(), new B() };

Оба A и B совместно используют object каких базовый класс, но было бы бесполезно и в основном бесполезно выводить это для типа массива.Можно было бы ожидать, что это будет IFoo, если что-нибудь, так что это нарушит принцип наименьшего удивления .Тем не менее, это не может быть сделано последовательно, как я иллюстрировал.

Самое безопасное и наиболее последовательное поведение здесь - просто не допускать вывода типов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...