Question

I have got class declared like this:

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

In that class I have this method:

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

I thought that this will be correct but I see red line under return statement and Resharper says that new SavedState(Width, Height) cannot be converted to TS. I don't know why. I thought that TS can be any class that extends SavedState but also SavedState itself. What can I do to correct it ?

Class saved state is very simple it looks like this:

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;
    }
}
Was it helpful?

Solution

Here's a small program illustrating one potential way to try and achieve what you want:

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);
        }
    }
}

Basically the idea is to use a new() constraint (thus all of your types derived from SaveState must have a default constructor) and object initializers. Of course this does mean that your SaveState class can't have private setters anymore.

OTHER TIPS

This has nothing to do with covariance; it's just impossible.

Since TS can be any class that extends SavedState, you cannot magically convert a base SavedState instance to whatever TS is.

For example, if I make a BoxGroup<MySpecialSavedState>, your code will try to convert a base SavedState object to a MySpecialSavedState, which is not possible.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top