Почему Array Covariance небезопасен? - PullRequest
0 голосов
/ 01 ноября 2018

Я читал о ковариации и контравариантности из этого блога и

ковариация на массиве запутала меня

Теперь, если у меня есть это

object[] obj= new string[5];
obj[0]=4;

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

class baseclass
    {

    }
    class client
    {
        static void Main()
        {
            object obj = new baseclass();
            obj = 4;

            Console.Read();
        }
    }

Ответы [ 2 ]

0 голосов
/ 01 ноября 2018

Объект массива типа T[] обладает тремя известными способностями:

  1. Любое значение, считанное из массива, может храниться в контейнере типа T.

  2. Любое значение, считанное из массива, может быть сохранено обратно в тот же массив.

  3. Любое значение, которое помещается в контейнер типа T, может быть сохранено в массиве.

Непустая ссылка типа T[] будет способна содержать ссылку на любой объект типа U[], где U происходит от T. Для любого возможного типа U, полученного из T, любое значение, считанное из U[], может быть сохранено в контейнере типа T, а также может быть сохранено обратно в тот же массив. Если контейнер типа T содержит ссылку на объект, который является производным от T, но не относится к типу U или к какому-либо типу, производному от U, то U[] будет неспособен содержать это ссылка.

Было бы неловко разрешить коду читать элемент из одного массива и записывать его обратно в тот же массив, не позволяя ему также запрашивать чтение элемента из одного массива и запись в другой. Вместо того, чтобы пытаться ограничить такие операции с помощью ограничений времени компиляции, C # вместо этого говорит, что если код пытается сохранить значение, хранящееся в T, в массиве, идентифицированном с помощью T[], такая операция будет успешной, если T является нулевым или идентифицирует объект типа, не производного от типа элемента фактического массива, идентифицируемого T[].

0 голосов
/ 01 ноября 2018

Это на самом деле сбивает с толку.

Когда вы говорите object[] objs = new string[4] {};, тогда objs - это на самом деле массив строк . Небезопасная ковариация массива небезопасна, потому что система типов обманывает вас . Вот почему это небезопасно . Вы думаете , что ваш массив может содержать целое в штучной упаковке, но это действительно массив строк, и он не может содержать ничего, кроме строк .

Ваш вопрос: «почему это небезопасно?», И затем вы приводите пример того, почему это небезопасно. Это небезопасно, потому что происходит сбой во время выполнения, когда вы делаете что-то, что выглядит как безопасное . Это нарушение самого основного правила системы типов: переменная на самом деле содержит значение типа переменной.

Для переменной типа object это не ложь. Вы можете хранить любой объект в этой переменной, так что это безопасно. Но переменная типа object[] является ложью. В этой переменной можно хранить вещи, которые не object[].

Это, на мой взгляд, худшая особенность C # и CLR. C # имеет эту функцию, потому что CLR имеет это. У CLR есть это, потому что у Java есть это, и разработчики CLR хотели иметь возможность реализовать Java-подобные языки в CLR. Я не знаю, почему у Java это есть; это ужасная идея, и им не следовало этого делать.

Теперь понятно?

...