A generic method can use contravariant/covariant types?

后端 未结 3 426
梦如初夏
梦如初夏 2020-12-31 19:00

I\'m writting a generalized method to use it in a special task at a T4 template. The method should allow me to use specialized types from a general interface. I thought abou

3条回答
  •  情话喂你
    2020-12-31 19:55

    If you want to inherit from a generic interface, see phoog's answer. If you are talking about trying to implement an interface co-variantly, that leads to my discussion below.

    Assume:

    internal interface IAnInterface { }
    
    public class SomeSubClass : IAnInterface { }
    
    public class AnotherSubClass : IAnInterface { }
    
    public GreatClass : IGreatInterface { ... }
    

    The problem with trying to implement the interface with a more derived (co-variant) argument is there's no guarante when this is called through an interface that an IAnInterface passed in will be a SomeSubClass instance. This is why it's not allowed directly.

    IGreatInterface x = new GreatClass();
    
    x.aMethodBeta(new AnotherSubClass());
    

    IF You could do covariance, this would fail because you would be expecting a SomeSubClass but would get a AnotherSubClass.

    What you could do is to do explicit interface implementation:

    class GreatInterface : IGreatInterface
    {
        // explicitly implement aMethodBeta() when called from interface reference
        object IGreatInterface.aMethodBeta(IAnInterface parameter)
        {
            // do whatever you'd do on IAnInterface itself...
            var newParam = parameter as SomeSubClass;
    
            if (newParam != null)
            {
                aMethodBeta(newParam);
            }
    
            // otherwise do some other action...
        }
    
        // This version is visible from the class reference itself and has the 
        // sub-class parameter
        public object aMethodBeta(SomeSubClass parameter)
        {
            // do whatever
        }
    }
    

    Thus, if you did this, your interface supports the generic, the class has a more specific method, but still supports the interface. The main difference is you'd need to handle the case where an unexpected implementation of IAnInterface is passed in.

    UPDATE: it sounds like you want something like this:

    public interface ISomeInterface
    {
        void SomeMethod(A someArgument);
    }
    
    public class SomeClass : ISomeInterface
    {
        public void SomeMethod(TA someArgument) where TA : SomeClass
        {
    
        }
    }
    

    This is not allowed, when you implement a generic method from an interface, the constraints must match.

提交回复
热议问题