Sam
Sam

Reputation: 15770

Why does this throw and exception?

I have a base controller:

Public MustInherit Class InjuredWorkerController(Of TManager As IInjuredWorkerManagerBase)

Then I have a home controller:

Public Class HomeController
    Inherits InjuredWorkerController(Of IInjuredWorkerManager)

IInjuredWorkerManager inherits IInjuredWorkerManagerBase

Why does this throw a cast exception:

Dim manager = CType(filterContext.Controller, InjuredWorkerController(Of IInjuredWorkerManagerBase)).Manager

Unable to cast object of type 'MyClaim.Controllers.HomeController' to type 'MyClaim.Controllers.InjuredWorkerController`1[SAIF.Web.Mvc.MyClaim.IInjuredWorkerManagerBase]'.

Upvotes: 0

Views: 89

Answers (1)

Christoffer Lette
Christoffer Lette

Reputation: 14846

You need to extract an interface for your InjuredWorkerController to make it work, since co- and contravariance only works with interfaces and delegates.

This code compiles and runs (C# console app, I'm not fluent in VB.Net...):

using System;

namespace TestApplication
{
    public interface IInjuredWorkerController<out TManager>
        where TManager : IInjuredWorkerManagerBase
    {
        TManager Manager { get; }
    }

    public abstract class InjuredWorkerController<TManager>
        : IInjuredWorkerController<TManager>
        where TManager : IInjuredWorkerManagerBase, new()
    {
        protected InjuredWorkerController()
        {
            Manager = new TManager();
        }

        public TManager Manager { get; private set; }
    }

    public interface IInjuredWorkerManagerBase
    {
        string Name { get; }
    }

    public interface IInjuredWorkerManager
        : IInjuredWorkerManagerBase {}

    public class InjuredWorkerManager : IInjuredWorkerManager
    {
        public string Name
        {
            get { return "Homer"; }
        }
    }

    public class HomeController
        : InjuredWorkerController<InjuredWorkerManager> {}

    internal class Program
    {
        private static void Main()
        {
            var controller = new HomeController();
            var manager = ((IInjuredWorkerController<IInjuredWorkerManagerBase>)controller).Manager;

            Console.Out.WriteLine(manager.Name);
            Console.ReadKey();
        }
    }
}

Eric Lippert's blog series on the subject is a must read.

Upvotes: 1

Related Questions