C # Passing the current instance of a generic class to another class

Recently, I began to study generics. I'm having trouble storing references to instances of generic classes. As you can see, my ListHandler class can store references to a specific type of BaseClass. I would like to register BaseClass instances myself, so I wanted to guarantee that they would use BaseParamClass by adding "where". In any case, it does not compile. β€œThis,” does not know that T is actually a base class, even with the keyword β€œwhere” in the class. I do not know what is wrong here, and I could not find the answer anywhere. I would appreciate advice / recommendations / solutions.
public class ListHandler
{
    private List<BaseClass<BaseParamClass>> list;

    public ListHandler()
    {
        list = new List<BaseClass<BaseParamClass>>();
    }

    public void Register(BaseClass<BaseParamClass> param)
    {
        list.Add(param);
    }
}

public class BaseClass<T> where T : BaseParamClass
{
    private ListHandler listHandler;

    public T Param { get; private set; }

    public BaseClass(ListHandler listHandler)
    {
        this.listHandler = listHandler;
        listHandler.Register(this); //throws error
    }
}
+4
source share
4

ListHandler ?

public class ListHandler<T>
{
    private List<BaseClass<T>> list;

    public ListHandler()
    {
        list = new List<BaseClass<T>>();
    }

    public void Register(BaseClass<T> param)
    {
        list.Add(param);
    }
}

public class BaseClass<T> 
{
    private ListHandler<T> listHandler;

    public T Param { get; private set; }

    public BaseClass(ListHandler<T> listHandler)
    {
        this.listHandler = listHandler;
        listHandler.Register(this); 
    }
}

, , BaseClass<T> , BaseClass<T>.

+1

, , , SO. , , ; , .

-

:

object a = new String(...);

!

List<object> c = new List<string>();  //Compiler error

, , object string. . , . . :

void Foo<T>() where T: BaseParamClass 
{
    BaseClass<BaseParamClass> a = new BaseClass<T>(); //Compiler error
}

T BaseParamClass . . , , Register, .

. . , , :

List<object> a = new List<string>();  //Compiler error

:

IEnumerable<object> e = new List<string>();  //Is OK

IEnumerable , :

interface IEnumerable<out T> 

, . , out : ...

interface IEnumerable<out T> 
{
    T Item[int index];
}

... :

interface IEnumerable<out T> 
{
    Add(T item); //Compiler error
}

- , , () .

, (, -), BaseClass<T>. , T, , .

, .

, , .

-

, , , . , , .

interface IStackable
{
    string Title { get; set; }
}

:

public class ListHandler 
{
    private readonly Dictionary<string, IStackable> list;

    public ListHandler()
    {
        list = new Dictionary<string, IStackable>();
    }

    public void Register(IStackable item)
    {
        list.Add(item.Title, item);
    }
}

public class BaseClass<T> : IStackable where T : BaseParamClass
{
    private ListHandler listHandler;

    public T Param { get; private set; }

    public BaseClass(ListHandler listHandler)
    {
        this.listHandler = listHandler;
        listHandler.Register(this);
    }

    public string Title { get; set; }
}

, , .

+1

, , . :

public class BaseParamClass
{
}

public class ListHandler 
{
    private List<IBase<BaseParamClass>> list;

    public ListHandler()
    {
        list = new List<IBase<BaseParamClass>>();
    }

    public void Register(IBase<BaseParamClass> param)
    {
        list.Add(param);
    }
}

public interface IBase<T> where T : BaseParamClass
{
    T Param {get; }
}

public class BaseClass : IBase<BaseParamClass>
{
    private ListHandler listHandler;

    public BaseParamClass Param { get; private set; }

    public BaseClass(ListHandler listHandler)
    {
        this.listHandler = listHandler;
        listHandler.Register(this); 
    }
}

DotNetFiddle

0

.

BaseClass<T> , :

public class BaseClass
{
    protected ListHandler listHandler;

    public BaseClass(ListHandler listHandler)
    {
        this.listHandler = listHandler;
    }
}

public class BaseClass<T> : BaseClass where T : BaseParamClass
{

    public T Param { get; private set; }

    public BaseClass(ListHandler listHandler)
        : base(listHandler)
    {
        listHandler.Register(this); // Compiles nicely! Yay!
    }
}

list ListHandler private List<BaseClass> list;. , BaseClass. BaseClass<T> ListHandler. :

public class ListHandler
{
    private List<BaseClass> list;

    public ListHandler()
    {
        list = new List<BaseClass>();
    }

    public void Register<T>(BaseClass<T> param) where T : BaseParamClass
    {
        list.Add(param);
    }

    public BaseClass<T> Fetch<T>() where T : BaseParamClass
    {
        return list.Select(x => x as BaseClass<T>).Where(x => x != null).FirstOrDefault();
    }
}

, public class FooParam : BaseParamClass { }, :

ListHandler listHandler = new ListHandler();
BaseClass<FooParam> baseClass = new BaseClass<FooParam>(listHandler);
BaseClass<FooParam> baseClass2 = listHandler.Fetch<FooParam>();

Console.WriteLine(object.ReferenceEquals(baseClass, baseClass2));

The result of this code is Truewritten to the console - this means that I can successfully extract the instance BaseClass<FooParam>from ListHandler.

0
source

Source: https://habr.com/ru/post/1689927/


All Articles