0

I have a generic interface where the type constraint is an abstract base class.

So the implementations may be of different implementations.

Although this is fine, when I try to return a concrete implementation (such as ITestImplementation) from a method which is set to return the interface (eg ITest), this throws various compile time errors in Visual Studio about implicit casts.

Code:

ITest<Control>
{
  void Execute();
}

I use this interface in various places and return a method as above. Maybe I should use a generic type placeholder.

Is this not possible?

Thanks

blade3
  • 1
  • 1
  • 1
    Please post a small, complete example that demonstrates the problem. – Andrew Hare Nov 17 '09 at 22:52
  • 3
    I'm sure this makes perfect sense to you, but I cannot make heads nor tails of it. Not only should you post code that demonstrates the problem, but it would be helpful also to see the error messages. The error messages are frequently correct diagnoses of the problem; if they are, read the error messages carefully. If they are not, I need to know what the case is so that we can fix the misleading error message. – Eric Lippert Nov 17 '09 at 23:08

3 Answers3

3

What you want is generic variance; specifically, you want Interface1 to be covariant.

Generic variance is not supported in C# 3. It will be in C# 4. Your code will work if you say

interface Interface1<out T>

However, you are then required to only use T in such a manner that the interface conversion you want is provably safe.

Consider an example where it would not be legal to see what I mean. Suppose you have an object which implements IList<Mammal>. It is in fact a list of mammals. You wish to convert it to IList<Animal>, figuring "a list of mammals can be used as a list of animals". But you can insert a Snake into a list of animals, which would then attempt to put a snake into a list of mammals, and crash. Lists cannot be covariant safely.

If you can prove to the compiler that your interface is safe for covariance, then C# 4 will let you do this. I'll be posting a detailed description of what the requirements are for safety on my blog in the next couple of weeks.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
1

Not 100% sure what you are shooting for but check out the discussions of covariance and contravariance to see if your scenerio is possible now or if you need to wait for c# 4.0.

https://stackoverflow.com/questions/1078423/c-is-variance-covariance-contravariance-another-word-for-polymorphism

Community
  • 1
  • 1
Chris Schoon
  • 2,145
  • 1
  • 17
  • 11
0

Apologies, the code was at work, but I recreated the error at home:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ArtOfTest.WebAii.Controls.HtmlControls;

namespace iCrawler.Code
{
    interface Interface1<T> where T : HtmlControl
    { // May use T for future methods which will be generic in nature eg work with a generic collection of instances of T (not depicted in the method signature below)
        void DoStuff();
    }

    class Child1 : Interface1<ArtOfTest.WebAii.Controls.HtmlControls.HtmlAnchor>
    {
        public void DoStuff()
        {
            throw new NotImplementedException();
        }
    }

    class Test
    {

        public Interface1<HtmlControl> ReturnExperiment()
        {
            Child1 child1 = new Child1();
            return child1;
        }

    }
}

On the "return child1" line, I get the error below:

Error   1   Cannot implicitly convert type 'iCrawler.Code.Child1' to 'iCrawler.Code.Interface1<ArtOfTest.WebAii.Controls.HtmlControls.HtmlControl>'. An explicit conversion exists (are you missing a cast?)    C:\Projects\Current\iCrawler\iCrawler\iCrawler\Code\Interface1.cs   28  20  iCrawler

Also, I'm pretty sure return Child1 (where Child1 is the type not the variable) was perfectly legal?

Thanks

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
blade3
  • 1