'Can I pass a base class type as a generic parameter to an interface

Can I pass base class types as a generic parameters to interfaces which are implemented in the context of the successors of that base class in C#.

Let's imagine there is an interface:

public interface IElement<T>
{
   Collection<T> Neighbors { get; }   
}

I want to implement this interface like this:

public class Element : IElement<object>
{
   public Collection<Neighbor> Neighbors { get; set; }
}

I also even tried achieving it like this:

public class Element : IElement<IObject>
{
   public Collection<Neighbor> Neighbors { get; set; }
}

Where IObject and Neighbor are:

public interface IObject
{ 
}

public class Neighbor : IObject
{
   // some props
}

In either way I get the same error: Element does not implement the IElement interface - member Neighbors cannot implement IElement.Neighbors, because they have different return types.

The purpose of this is to make an abstraction of the datatypes and use a simpler version of them in the business logic:

public class BusinessLogic
{
   bool predicate1;
   bool predicate2;
    
   // variant 1
   public bool CanIDoSomething(IElement<object> element)
   {
      return element.Neighbours.Any() && predicate1 && predicate2;
   }

   // variant 2
   public bool CanIDoSomething(IElement<IObject> element)
   {
      return element.Neighbours.Any() && predicate1 && predicate2;
   }
}

The problem goes even deeper if I try to use IEnumerable instead of Collection:

public interface IElement<T>
{
   IEnumerable<T> Neighbors { get; }   
}

What am I missing and is there a workaround for this?


EDIT:

I Made the IElement interface generic parameter covariant as follows:

public interface IElement<out T>
{
   IEnumerable<T> Neighbors { get; }
}

But this does not solve the interface implementation error.

The only way I can make the class to implement the interface correctly is by doing this:

public class Element : IElement<IObject>
{
   public Collection<Neighbor> Neighbors { get; set; }

   IEnumerable<IObject> IElement<IObject>.Neighbors => Neighbors;
}

Is there a limitation that causes the covariance to not be applied implicitly when implementing an interface?

Is there a more elegant way of doing this?

I want to keep the IObject interface instead of using object directly because in the IObject interface if I ever need I can place a certain subset of the properties of the Neighbor class.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source