none
Generic class inherits from a non-generic class? RRS feed

  • Question

  • I've been reading about how to do what the title says but I can't find a definitive set of rules or many articles don't even mention this case. For instance: here. I'm totally new to C# generics but I hope you understand what I'm trying to do:

    // I can't edit this class as it's part of a library

    public abstract class ScriptableObject { //... } public abstract class Unit<T> : ScriptableObject where T : Unit { public T connection; } public class CameraUnit : Unit<MonitorUnit> { // assign a MonitorUnit to connection } public class MonitorUnit : Unit<CameraUnit> { // assign a CameraUnit to connection }

    The underlined `Unit` in the code throws this error:

    "Using the generic type 'Unit<T>' requires 1 type arguments".

    The underlined `MonitoUnit` throws:

    "The type 'CameraUnit' cannot be used as type [...]. There's no implicit conversion from 'CamerUnit' to  'Unit'".

    My question is more about where to read about this (generic derived from non-generic) than about the errors, which BTW I have no idea where they could arise from.

    Thanks in advance.


    Tuesday, January 16, 2018 12:07 AM

Answers

  • Hello andreiMarianMirea,

    >>"Using the generic type 'Unit<T>' requires 1 type arguments".

    The issue is that you don't have a Unit class, you just have a generic class Unit<T>. You need to define a Unit class.

    public class Unit
    	{
    	}
    public abstract class Unit<T> : ScriptableObject where T:Unit
    	{
    		public T connection;
    	}
    

    >>"The type 'CameraUnit' cannot be used as type [...]. There's no implicit conversion from 'CamerUnit' to  'Unit'".

    The issues always occur with generic classes covariance and contravariance, which are related to inheritance of type parameters. The MSDN document has detailed discussion here.

    The quickly fixed as below.

    public class CameraUnit:Unit
    	{
    	}
    public class MonitorUnit : Unit<CameraUnit>
    	{
    		// assign a CameraUnit to connection
    	}
    
    	

    Best regards,

    Neil Hu


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, January 16, 2018 2:37 AM
    Moderator

All replies

  • Greetings Andrei.

    I know it's annoying to ask a particular question only to be answered with "That's not your real problem, what you should be doing is...". But that's what I'm about to do. Sorry.

    I don't think your problems have anything to do with deriving a generic class from a non-generic one. Although I can't be sure, because I really can't see what you are trying to do.

    The error you are getting are because you are going round in circles, using Unit as a generic type identifier for itself, then using CameraUnit and MonitorUnit as type identifiers for each other. And I think the reason for you doing that is because you are trying to use generics where it is not appropriate.

    My best guess is, you want something like the following.

       public abstract class Unit : ScriptableObject
       {
          public Unit connection;
       }
    
       public class CameraUnit : Unit
       {
          public CameraUnit()
          {
             connection = new MonitorUnit();
          }
       }
       public class MonitorUnit : Unit
       {
          public MonitorUnit()
          {
             connection = new CameraUnit();
          }
       }

    Which doesn't use generics at all.

    But it's possible I'm missing something.

    Tuesday, January 16, 2018 1:58 AM
  • Hello andreiMarianMirea,

    >>"Using the generic type 'Unit<T>' requires 1 type arguments".

    The issue is that you don't have a Unit class, you just have a generic class Unit<T>. You need to define a Unit class.

    public class Unit
    	{
    	}
    public abstract class Unit<T> : ScriptableObject where T:Unit
    	{
    		public T connection;
    	}
    

    >>"The type 'CameraUnit' cannot be used as type [...]. There's no implicit conversion from 'CamerUnit' to  'Unit'".

    The issues always occur with generic classes covariance and contravariance, which are related to inheritance of type parameters. The MSDN document has detailed discussion here.

    The quickly fixed as below.

    public class CameraUnit:Unit
    	{
    	}
    public class MonitorUnit : Unit<CameraUnit>
    	{
    		// assign a CameraUnit to connection
    	}
    
    	

    Best regards,

    Neil Hu


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, January 16, 2018 2:37 AM
    Moderator
  • I don't know if this does what you need done but it builds and executes.

    public abstract class ScriptableObject {    }
    
    public abstract class Unit<T> : ScriptableObject
    {
        public T connection;
    }
    
    public class CameraUnit : Unit<MonitorUnit>
    {
        string name = "From CameraUnit";
        public CameraUnit() { Console.WriteLine(name); }       
    }
    
    public class MonitorUnit : Unit<CameraUnit>
    {
        string name = "From MonitorUnit";
        public MonitorUnit() { Console.WriteLine(name); }
    }
    



    Sam Hobbs
    SimpleSamples.Info

    Tuesday, January 16, 2018 6:29 AM
  • Thank you all. What I'm trying to achieve is pretty much what you coded, @Ante Meridian, but with the addition of enforcing `connector` of any Unit derived object to take also a `Unit` derived object.

    Also, thanks Ante Meridian for revealing the fact that I was going on in circles.

    @Fei Hu, in the light of your code and what Ante Meridian said, first error is now obvious. About the second error, once I corrected the first one, it also went away.

    Eventually it looks like what needed is different from what I asked. And Fei's answer is straight to the point of my question.

    Tuesday, January 16, 2018 4:36 PM