0
votes

Can I use raw type in C# like Java or is there a workaround for this? I know using Raw Type in Java is bad practice but that can solve my current problem. I have an object that has a field holding a Pool, so that it can return to that Pool whenever it's done with its job.

    //C#
    public class MyObject : IPoolable
    {
        public Pool<MyObject> pool;
    }

But if there is a new kind of object (ex: MovableObject), I want my pool field has Pool<MovableObject> not Pool<MyObject>. (There are also many kinds of objects derived from MovableObject or MyObject). In Java, I could define pool field a raw type of Pool so that there is no compiling error.

    //Java
    public class MyObject implements IPoolable
    {
        public Pool pool;
    }

I'm using a method to return all kinds sof objects in both versions. In Java, it works well but in C#, it has compiling error.

    //Java
    static public <T extends MyObject> T createObject(Class<T> type) {
        Pool<T> pool = Pools.get(type);
        T obj= pool.obtain();
        obj.setPool(pool); //This won't have any problem since it is raw type
        return obj;
    }
    //C#
    public static T CreateObject<T>() where T : MyObject
    {
        Pool<T> pool = Pools.GetPool<T>();
        T obj= pool.Obtain();
        obj.Pool = pool; //Error: cannot convert Pool<T> to Pool<MyAction>
        return obj;
    }

Edit 1: Providing other classes and Minimal, Reproducible Example

public interface IPoolable
{
    void Reset();
}
public abstract class Pool<T> where T : IPoolable
{
    private readonly Stack<T> freeObjects = new Stack<T>();

    public Pool() { }

    protected abstract T InstantiateObject(object[] args);

    public T Obtain(object[] args = null)
    {
        return freeObjects.Count == 0 ? InstantiateObject(args) : freeObjects.Pop();
    }
    public void Free(T obj)
    {
        if (obj != null)
        {
            freeObjects.Push(obj);
            Reset(obj);
        }
    }
    protected virtual void Reset(T obj)
    {
        obj.Reset();
    }
    public void Clear()
    {
        freeObjects.Clear();
    }
}

//ReflectionPool
public class ReflectionPool<T> : Pool<T> where T : IPoolable
{
    public ReflectionPool() : base()
    {
    }

    protected override T InstantiateObject(object[] args)
    {
        return (T)Activator.CreateInstance(typeof(T), args);
    }

}
public class Pools
{
    static private readonly Dictionary<Type, object> typePools = new Dictionary<Type, object>();

    static public Pool<T> GetPool<T>(int max) where T : IPoolable
    {
        Type type = typeof(T);
        if (!typePools.TryGetValue(type, out object pool))
        {
            pool = new ReflectionPool<T>();
            typePools.Add(type, pool);
        }
        return (Pool<T>)pool;
    }

    static public Pool<T> GetPool<T>() where T : IPoolable
    {
        return GetPool<T>(100);
    }
}

So in MyObject class, there is a method making my object doing something, after completing it, the current object need to be returned to Pool

//Base Object
public abstract class MyObject : IPoolable
{
    public Pool<MyObject> pool; //This is still a problem
    public void CallMe()
    {
        if (Act()) //If this object completing acting
        {
            ToPool();
        }
    }
    public abstract bool Act();
    public void ToPool()
    {
        pool.Free(this);
        pool = null;
    }

    public abstract void Reset();
}

//Movable Object
public class MovableObject : MyObject
{
    //public Pool<MyObject> pool; //Put this here as comment because I want it become Pool<MovableObject>
    public override bool Act()
    {
        return true; //Return false if not reach destination
    }

    public override void Reset() { }

    public override string ToString()
    {
        return "Movable";
    }
}
//I'm using this class for create object I want
public class ObjectFactory
{
    public static T CreateObject<T>() where T : MyObject 
    {
        Pool<T> pool = Pools.GetPool<T>();
        if(pool != null)
        {
            T obj = pool.Obtain();
            obj.pool = pool; //Error here: Cannot implicitly convert type 'Pool<T>' to 'Pool<MyObject>'
            return obj;
        }
        return null;
    }

    public static MovableObject MovableObject()
    {
        return CreateObject<MovableObject>();
    }
}

Edit 2: Re-Updated code in edit 1

You have something as dynamics objects in C#. You can create them to cast them to it. I don't Java very well, is this what you are looking for? docs.microsoft.com/en-us/dotnet/csharp/programming-guide/types/… You can do some very stupid things with it, and there is a high risk on runtime errors.M1sterPl0w
Could you please provide a minimal reproducible example? Missing at the moment are IPoolable, Pool<T>, and Pools.Enigmativity
@M1sterPl0w - there are very few occasions where dynamic is a good answer.Enigmativity
@Enigmativity if you read my comment a little better, I do not imply that it is a good idea to use it.M1sterPl0w
Have you considered a covariant interface e.g. IPool<out T>?Johnathan Barclay