-1

Why is in the below example Base<BaseResult<bool, object>, bool, object> not a valid base class for Concrete<object>? Base<BaseResult<bool, object>, bool, object> is base to SpecializedBase<bool, object>, and SpecializedBase<bool, object> seems like a proper base for Concrete<object>?

public abstract class Base<TResult, TOutcome, TOutput>
        where TResult : BaseResult<TOutcome, TOutput>
        where TOutput : class
    {
    }

    public class BaseResult<TOutcome, TOutput>
    {
    }

    public abstract class SpecializedBase<TResult, TOutput> :
        Base<SpecializedResult<TOutput>, bool, TOutput>
        where TOutput : class
    {
    }

    public class SpecializedResult<TOutput> : BaseResult<bool, TOutput>
    {
    }

    public class Concrete<TOutput> : 
        SpecializedBase<SpecializedResult<TOutput>, TOutput>
        where TOutput : class
    {
    }

    static class Program {
        static void main()
        {
            // #1: works
            SpecializedBase<SpecializedResult<object>, object> obj;

            obj = new Concrete<object>();

            // #2: works
            Base<SpecializedResult<object>, bool, object> obj2;

            obj2 = new Concrete<object>();

            // #3: doesn't work:
            // Cannot implicitly convert type 'TypeTest.Concrete<object>' to 'TypeTest.Base<TypeTest.BaseResult<bool, object>, bool, object>'
            Base<BaseResult<bool, object>, bool, object> obj3;

            obj3 = new Concrete<object>();
        }
    }
}

user182917
  • 1,688
  • 2
  • 14
  • 17

1 Answers1

3

Let's try to resolve the type step by step.

Concrete<object> is SpecializedBase<SpecializedResult<object>, object>. SpecializedBase<SpecializedResult<object>, object> is Base<SpecializedResult<object>, bool, object>.

And that's it. Base inherits directly from Object, so ultimately the least derived type is Base<TResult, TOutcome, TOutput> with TResult set to SpecializedResult<object>, TOutcome to bool and TOutput to object. This type is invariant and thus Base<SpecializedResult<object>, bool, object> is not Base<BaseResult<bool, object>, bool, object>.

You can find more on generic variance in the MSDN docs, this SO question and this SO question (and probably a thousand other places as well, it's a notoriously complicated concept to wrap your head around).

V0ldek
  • 9,623
  • 1
  • 26
  • 57