Почему следующее не компилируется? (включает дженерики и наследование в c #) - PullRequest
3 голосов
/ 25 июня 2010

Это составляет: </p> <pre><code> class ReplicatedBaseType { } class NewType: ReplicatedBaseType { } class Document { ReplicatedBaseType BaseObject; Document() { BaseObject = new NewType(); } }

Но это не так:

    class DalBase<T> : where T: ReplicatedBaseType
    {
    }

    class DocumentTemplate
    {
    DalBase<ReplicatedBaseType> BaseCollection;
    DocumentTemplate ()
    {
    BaseCollection= new DalBase<NewType>(); // Error in this line. It seems this is not possible
    }
    }

В чем причина?

Ответы [ 5 ]

8 голосов
/ 25 июня 2010

Как говорит Андрей, вы хотите (универсальный) ковариация .Однако:

  • Общая дисперсия поддерживается только в C # 4
  • Общая дисперсия не поддерживается в классах
  • В реальной ситуации это может быть небезопасно.

Чтобы перейти к финальной точке, предположим, что DalBase<T> имеет такой метод:

void AddEntity(T entity)

Теперь у вас есть что-то подобное, которое вы хотите иметь возможность компилировать -но, очевидно, это было бы опасно:

DalBase<Fruit> fruitDal = new DalBase<Banana>();
fruitDal.AddEntity(new Apple());

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

Недавно я провел часовую беседу об общей дисперсии, которая может оказаться полезной, если вы хотите узнать больше - см. Страницу видео NDC 2010 и выполните поиск по слову «дисперсия».В качестве альтернативы вы можете прочитать сообщения Эрика Липперта в блоге на тему - но имейте в виду, что это, вероятно, займет больше часа;)

6 голосов
/ 25 июня 2010

Дисперсия существует в C # 4.0, ориентируясь на .NET 4), но ограничивается интерфейсами и использованием in / out (о, и массивов ссылочных типов) Например, чтобы сделать ковариантную последовательность:

class DalBase<T> : IEnumerable<T> where T: ReplicatedBaseType
{
    public IEnumerator<T> GetEnumerator() {throw new NotImplementedException();}
    IEnumerator IEnumerable.GetEnumerator() { throw new NotImplementedException(); }
}

class DocumentTemplate
{
    IEnumerable<ReplicatedBaseType> BaseCollection;
    DocumentTemplate()
    {
        BaseCollection = new DalBase<NewType>(); // Error in this line. It seems this is not possible
    }
}

Но кроме этого ... нет. Придерживайтесь либо неуниверсальных списков (IList), либо используйте ожидаемый тип списка.

2 голосов
/ 25 июня 2010

Это не работает, потому что DalBase<NewType> не является DalBase<ReplicatedBaseType> - дженерики не имеют ко / противо-дисперсии.В C # 4 вы можете получить общую дисперсию, но только для интерфейсов и делегатов.

1 голос
/ 25 июня 2010

нужная вам функция называется «ковариация» и была представлена ​​только в C # 4.0 http://blog.t -lk.com / dot-net / 2009 / c-sharp-4-covariance-and-contravariance

Ваш код не выполняется, потому что нет такого приведения (как явного, так и неявного).Текущие правила C # (<= 3.0) запрещают это. </p>

для проверки возможных приведений см. §6.1.6 Спецификация C #

0 голосов
/ 25 июня 2010

Этот код компилируется в VS2010, net framework 4

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication2
{
    class ReplicatedBaseType
    {
    }

    class NewType : ReplicatedBaseType
    {
    }

    class Document
    {
        ReplicatedBaseType BaseObject;

        Document()
        {
            BaseObject = new NewType();
        }
    }
    interface DalBase<out T>  where T: ReplicatedBaseType
    {
    }

    class DalBaseExample<T> : DalBase<T> where T: ReplicatedBaseType
    {

    }
    class DocumentTemplate
    {
        DalBase<ReplicatedBaseType> BaseType;
        DocumentTemplate ()
        {
            BaseType = new DalBaseExample<NewType>(); // no error here
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...