Проблема ковариации в C # - PullRequest
       7

Проблема ковариации в C #

2 голосов
/ 05 января 2011

У меня есть класс, объявленный так:

internal private abstract class BoxGroup<TS> : IBoxGroup where TS : SavedState

В этом классе у меня есть этот метод:

protected virtual TS saveState() {
    return new SavedState(Width, Height);
}

Я думал, что это будет правильно, но я вижу красную линию под оператором return, и Решарпер говорит, что new SavedState(Width, Height) нельзя преобразовать в TS. Я не знаю почему. Я думал, что TS может быть любым классом, который расширяет SavedState, но также и SavedState сам по себе. Что я могу сделать, чтобы исправить это?

Состояние сохраненного класса очень просто, оно выглядит так:

private class SavedState {
    internal float Width { get; private set; }
    internal float Height { get; private set; }
    public SavedState(float width, float height) {
        Width = width;
        Height = height;
    }
}

Ответы [ 2 ]

6 голосов
/ 05 января 2011

Это не имеет ничего общего с ковариацией; это просто невозможно.

Поскольку TS может быть любым классом, расширяющим SavedState, вы не можете волшебным образом преобразовать базовый SavedState экземпляр в то, чем TS является.

Например, если я сделаю BoxGroup<MySpecialSavedState>, ваш код попытается преобразовать базовый SavedState объект в MySpecialSavedState, что невозможно.

2 голосов
/ 05 января 2011

Вот небольшая программа, иллюстрирующая один потенциальный способ попробовать и достичь того, что вы хотите:

using System;

namespace Test
{
    class SaveState
    {
        public int Width { get; set; }
        public int Height { get; set; }
    }

    class SaveStateWithPi : SaveState
    {
        public double Pi
        {
            get { return Math.PI; }
        }
    }

    class Program
    {
        public static T CreateSavedState<T>(int width, int height)
            where T : SaveState, new()
        {
            return new T
                       {
                           Width = width,
                           Height = height
                       };
        }

        static void Main(string[] args)
        {
            SaveState state = CreateSavedState<SaveStateWithPi>(5, 10);

            Console.WriteLine("Width: {0}, Height: {1}", state.Width, state.Height);
        }
    }
}

По сути, идея заключается в использовании ограничения new () (поэтому все ваши типы, производные от SaveState, должныконструктор по умолчанию) и инициализаторы объекта.Конечно, это означает, что у вашего класса SaveState больше не может быть частных сеттеров.

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