0

I'm trying to write a generic function like the example of the image below. The idea is to have a method that will receive a generic type that must inherit an abstract class that has a generic configuration which has another abstract class.

public class MainCode
{
    public MainCode()
    {
        Execute<DefaultOptions>();
    }

    public void Execute<T>() where T : BaseClassOptions<BaseClassConfiguration> { }
}

public class DefaultOptions : BaseClassOptions<DefaultConfiguration> { }

public abstract class BaseClassOptions<T> where T : BaseClassConfiguration
{
    public T Config { get; set; }
}

public class DefaultConfiguration : BaseClassConfiguration { }

public abstract class BaseClassConfiguration
{
    public string Host { get; set; }
}

But I got the following error:

Error

Could you please help me?

Enigmativity
  • 113,464
  • 11
  • 89
  • 172
Vinicius Andrade
  • 151
  • 1
  • 4
  • 22
  • 3
    Please don't post code as images. – Zer0 Apr 09 '20 at 05:12
  • 3
    Please don't post code as picture. It's now impossible for anybody else to find it in a search or just copy paste it into their own IDE to try things. Please post your code as a code block. – nvoigt Apr 09 '20 at 05:13
  • 1
    I'll always struggle to understand why, when putting code in is a matter of pressing `ctrl-c,ctrl-v` and posting a screenshot (the easiest possible way) involves launching snipping tool, creating a snip then doing `ctrl-c,ctrl-v`, clicking the button, waiting for the upload, moving the placeholder if needed etc... why people go the harder route.. – Caius Jard Apr 09 '20 at 05:21
  • 2
    In other news, have you seen this? https://stackoverflow.com/questions/17434851/why-does-a-generic-type-constraint-result-in-a-no-implicit-reference-conversion – Caius Jard Apr 09 '20 at 05:25
  • Sorry guys, I've wrote down the code here now. But can i do it without using interfaces? – Vinicius Andrade Apr 09 '20 at 06:43
  • 1
    Please look at the link posted by Caius Jard. The answer there explains clearly why `BaseClassOptions` (this would be the `Cage` from that example) can't be used as a `BaseClassOptions` (the `Cage` from the answer). To question if you can do it without interfaces depends on how your code actually work. If you can remove the generic `BaseClassOptions` wrapper around the `BaseClassConfiguration` and use that directly then I think it might work. But that depends on if that's possible or not. –  Apr 09 '20 at 07:04

1 Answers1

0

Maybe this will work for you?

    public MainCode()
    {
        Execute<DefaultOptions, DefaultConfiguration>();
    }

    public void Execute<T, T2>() where T : BaseClassOptions<T2> where T2: BaseClassConfiguration
    { }

The problem is that BaseClassOptions<BaseClassConfiguration> is not the base class for the DefaultOptions, that's why you get this error. It happens because type parameters on generic classes are neither covariant nor contravariant, i.e. there is no inheritance relationship between specializations of the same generic class. If you don't want to use interfaces it may worth to say compiler directly what class to use as a generic parameter with your base type.

scor4er
  • 1,580
  • 12
  • 23
  • Can you please explain how this might work for the OP? And why his existing code doesn't work? – Enigmativity Apr 09 '20 at 08:16
  • @Enigmativity, I added some extra information, maybe now the answer is a bit more useful. – scor4er Apr 09 '20 at 08:40
  • I've already did this and it worked, but my point is: But I can't understand why i can't use it like in my code example.What I mean is: DefaultOptions already defines which type of BaseConfiguration I'll use, passing it to the base class. It makes no sense to me pass DefaultConfiguration as a generic type in my Execute function – Vinicius Andrade Apr 09 '20 at 11:39