Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic of Templates Error

Tags:

c#

generics

I'm attempting to make a list of templated classes, passing in a base class to the template. It seems however, that this isn't allowed. Is there a way to circumvent this restriction, or restructure my code more appropriately?

Here is an abstract example:

using System;
using System.Collections.Generic;

namespace TempInherit
{
    abstract class Shape{}

    class Triangle : Shape{}
    class Square : Shape{}

    class ShapeHolder<T>{}

    class MainClass
    {
        public static void Main(string[] args)
        {
            // list of base class, add subclass - works
            List<Shape> shapes = new List<Shape>();
            shapes.Add(new Triangle());
            shapes.Add(new Square());

            // list of holders of base class, add holders of subclass - fails
            List<ShapeHolder<Shape>> shapeHolders = new List<ShapeHolder<Shape>>();
            shapeHolders.Add(new ShapeHolder<Triangle>());
            shapeHolders.Add(new ShapeHolder<Square>());
        }
    }
}

Which yields:

Error CS1502: The best overloaded method match for `System.Collections.Generic.List>.Add(TempInherit.ShapeHolder)' has some invalid arguments (CS1502) (TempInherit)

Error CS1503: Argument #1' cannot convert TempInherit.ShapeHolder' expression to type `TempInherit.ShapeHolder' (CS1503) (TempInherit)

like image 882
Josh Avatar asked Nov 21 '25 19:11

Josh


1 Answers

covariance problem :

You may create an interface IShapeHolder<out T>, as generic parameters on interfaces can be covariant (but not on classes)

something like that

public class Shape
    {
    }
    public class Triangle : Shape
    {
    }
    public class Square : Shape
    {
    }
    //T generic parameter is covariant (out keyword)
    public interface IShapeHolder<out T> where T : Shape
    {
    }
    public class ShapeHolder<T>  : IShapeHolder<T> where T: Shape
    { 
    }

then,

var shapes = new List<Shape>();
shapes.Add(new Triangle());
shapes.Add(new Square());

// list of holders of base class, add holders of subclass - fails no more
var shapeHolders = new List<IShapeHolder<Shape>>();
shapeHolders.Add(new ShapeHolder<Triangle>());
shapeHolders.Add(new ShapeHolder<Square>());
like image 179
Raphaël Althaus Avatar answered Nov 24 '25 08:11

Raphaël Althaus



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!