C#中的协方差问题

时间:2011-01-05 02:07:06

标签: c# generics covariance contravariance

我的课程声明如下:

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

在那堂课中,我有这种方法:

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

我认为这是正确的,但我在return语句下看到红线,Resharper说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 个答案:

答案 0 :(得分:6)

这与协方差无关;这是不可能的。

由于TS可以是任何扩展SavedState的类,因此您无法将基本SavedState实例神奇地转换为TS。{/ p>

例如,如果我制作BoxGroup<MySpecialSavedState>,您的代码会尝试将基础SavedState对象转换为MySpecialSavedState,这是不可能的。

答案 1 :(得分:2)

这是一个小程序,展示了尝试实现您想要的一种潜在方式:

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类不能再拥有私有的setter了。