Обобщения и наследование в C # - PullRequest
4 голосов
/ 20 августа 2010

У меня есть класс сущностей, созданный дизайнером E-R, который я немного изменил. Это декларация:

public abstract partial class Preference<T> : EntityObject, IPreference<T>

Затем существует другой класс сущности, объявленный следующим образом:

public partial class BoolPref : Preference<bool>

поэтому BoolPref наследуется от Preferences<bool>. Теперь у меня есть это сгенерированное свойство:

public ObjectSet<Preference<object>> Preferences
    {
        get
        {
            if ((_Preferences == null))
            {
                _Preferences = base.CreateObjectSet<Preference<object>>("Preferences");
            }
            return _Preferences;
        }
    }
    private ObjectSet<Preference<object>> _Preferences;

Когда я пытаюсь добавить новый BoolPref к этому объектному набору следующим образом

context.Preferences.AddObject(new BoolPref ());

Я получаю ошибку во время компиляции.

Как я могу добавить экземпляры BoolPref в настройки? Где таинственная ошибка?

Ответы [ 3 ]

13 голосов
/ 20 августа 2010

Предположим, что Preference<T> имеет свойство чтения-записи с именем Value типа T. Теперь предположим, что система типов работает так, как вам хотелось бы:

var set = new ObjectSet<Preference<object>>();
set.Add(new Preference<bool>());
set.First().Value = "hello"; 

Это допустимо во время компиляции, поскольку установлено.First (). Значение имеет тип объекта времени компиляции, а не bool.Но во время выполнения он имеет тип bool, и вы только что вызвали метод установки, который принимает bool и передает строку , что приводит к повреждению памяти в CLR, которая затем падает и ужасно умирает.

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

2 голосов
/ 20 августа 2010

Короткий ответ заключается в том, что генерики из коробки не обрабатывают полиморфизм так же, как «нормальные» объекты обрабатывают полиморфизм - Preference<object> и Preference<bool> - это два взаимно несовместимых случая, когда Preference<T> несупертип / подтип.

Хорошая новость заключается в том, что с .NET 4.0, вы можете использовать ковариацию для получения желаемого эффекта.

Другая проблема здесь - это я 'Я не уверен, как EF сможет обрабатывать ваш класс с точки зрения постоянства, поскольку он, вероятно, не знает, что делать с Preference<T>.

1 голос
/ 20 августа 2010

Способ обойти это - иметь интерфейс IPreference, который представляет базовое значение как объект, так что вы можете иметь ObjectSet<IPreference>. Явная реализация Preference<T> IPreference должна затем проверить во время выполнения, предоставляются ли ей значения, соответствующие базовому типу.

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