Почему нет общей дисперсии для классов в C # 4.0? - PullRequest
55 голосов
/ 29 апреля 2010

Если у нас есть это для интерфейсов, почему у нас нет этого также для классов? С какой проблемой мы столкнемся при его использовании?

Ответы [ 3 ]

106 голосов
/ 29 апреля 2010

Предположим, у вас был класс C<T>, который был ковариантным в T. Как может выглядеть его реализация? T должен быть только вне. Это означает, что C<T> не может иметь метод, который принимает T, любое свойство типа T с установщиком, или любое поле типа T , потому что поля логически совпадают с установщиками свойств; Т входит.

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

В вышеприведенном комментарии был задан пример того, где это было бы полезно. Рассмотрим следующий эскиз:

sealed class Stack<out T>
{
    private readonly T head;
    private readonly Stack<T> tail;
    public T Peek() { return head; }
    public Stack<T> Pop() { return tail; }
    public Stack(T head, Stack<T> tail)
    {
        this.tail = tail;
        this.head = head;
    }
}
static class StackExtensions
{
    public static Stack<T> Push<T>(this Stack<T> tail, T head) 
    {
        return new Stack<T>(head, tail);
    }
    public static bool IsEmpty<T>(this Stack<T> stack)
    {
        return stack == null;
    }
}

Предположим, у вас были ковариантные классы. Теперь вы можете сказать

Stack<string> strings = null;
strings = strings.Push("hello");
strings = strings.Push("goodbye");
Stack<object> objects = strings;
objects = objects.Push(123);

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

2 голосов
/ 29 сентября 2010

Команда .NET вместе с командами C # и VB.NET располагают ограниченными ресурсами, работа, которую они проделали над совместной и противоположной , решает большую часть реальной проблемы . Системы типов очень сложны для понимания - решение, которое работает в 99,9999% случаев, недостаточно хорошо, если в других случаях оно приводит к небезопасному коду.

Я не думаю, что стоимость / время поддержки спецификаций со-и контравариантности (например, «in» / «out») для методов класса имеет достаточно большое значение. Я вижу очень мало случаев, когда их можно было бы использовать - из-за отсутствия множественного наследования классов.

Вы бы предпочли еще 6 месяцев для .net, чтобы получить эту поддержку?


Еще один способ думать об этом в .net

  • Интерфейсы / делегаты - используются для моделирования системы концептуальных типов приложения
  • Класс используются для реализации вышеуказанных типов
  • Наследование классов используется для уменьшения дублирования кода при выполнении вышеуказанного
  • ко- и контравариантность относится к системе концептуального типа приложения
2 голосов
/ 29 апреля 2010
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...