# [.net] Mess with generics [sad]

This topic is 4931 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi again! I'm new to generics so I've probably got this all wrong :'( Firstly I'll explain that resource pools derived from ResourcePoolBase hold resources derived from ResourceItemBase. ResourceItemBase needs to hold a reference to its pool. In its constructor it takes a reference to its pool and adds itself to it (and keeps the pool) Before, I had the generic types as you'd expect: public abstract class ResourcePoolBase<itemType> : NamedDataPool<itemType> where itemType : ResourceItemBase public abstract class ResourceItemBase<> : INameable However, the ResourceItemBase needs to know the pool type to take it as a parameter and be able to add itself. Of course, adding the constraint for the pool type means that the ResourceItemBase needs to know the itemType [sad]: public abstract class ResourcePoolBase<itemType, poolType> : NamedDataPool<itemType> where itemType : ResourceItemBase<itemType, poolType> where poolType : ResourcePoolBase<itemType, poolType> public abstract class ResourceItemBase<itemType,poolType> : INameable where itemType : ResourceItemBase<itemType, poolType> where poolType : ResourcePoolBase<itemType, poolType> The error where the ResourceItemBase adds itself to the pool is: Error 157 Argument '1': cannot convert from 'DirectXEngines.ResourceItemBase<itemType,poolType>' to 'itemType' and itemType is defined as above - the very same. No conversion is needed! But I think I messed it up with the cyclic restrictions :( Any solutions...really hard so major rates!

##### Share on other sites
Looks like a cyclic dependency...

You can solve this by creating an interface IPoolData
And then implement IPoolData by the ResourcePoolBase class and refer to IPoolData in:

public abstract class ResourceItemBase<itemType,poolType> : INameable
where itemType : ResourceItemBase<itemType, poolType>
where poolType : IPoolData

Cheers

##### Share on other sites
Thanks ernow - that would work if I only needed to add and remove using the pool, but I need to use the pool in other places too - I used to cast up like so:

in ResourceItemBase
/// <summary>
/// Gets the pool that the <see cref="ResourceItemBase"/> is kept in.</summary>
public ResourcePoolBase ResourcePool {
get {return m_ResourcePool;}
}

in Texture
/// <summary>
/// Gets the pool that the <see cref="Texture"/> is kept in.</summary>
public TexturePool TexturePool {
//WILL ALWAYS SUCCEED BECAUSE TYPE ENFORCED IN CONSTRUCTOR
get {return base.ResourcePool as TexturePool;}
}

but I'm sure the cast from ResourcePoolBase<ResourceItemBase> to TexturePool<Texture> failed even though the latter pool and its type are both derived!

##### Share on other sites
Right, I've changed it back now...that assembly compiles and it's all lovely.

However, it isn't going to let me win that easily. Trouble when deriving :(

Here's one of the base constructors:
protected ResourceItemBase(ResourcePoolBase<ResourceItemBase> resourcePool, string name){	if (resourcePool == null) throw new System.ArgumentNullException("resourcePool");	m_ResourcePool = resourcePool;	m_Name = name;	//Add this resource to the resource pool	m_ResourcePool.Add(this);}

and here's a constructor from the derived class:
protected VideoResourceItemBase(VideoResourcePoolBase<VideoResourceItemBase> videoResourcePool, string name): base(videoResourcePool, name){}

and on that last piece of code...

Argument '1': cannot convert from 'DirectXEngines.D3DGraphicsEngine.VideoResourcePoolBase<DirectXEngines.D3DGraphicsEngine.VideoResourceItemBase>' to 'DirectXEngines.ResourcePoolBase<DirectXEngines.ResourceItemBase>'

It won't even let me downcast :( What's going on?! [sad]

##### Share on other sites
Don't take it bad, but it really looks like a mess!
I don't understand why you need to make items generic in the first place ? You said: "the ResourceItemBase needs to know the pool type to take it as a parameter and be able to add itself".

abstract class ResourcePoolBase<itemType> : NamedDataPool<itemType> where itemType : ResourceItemBase{}abstract class ResourceItemBase : INameable{   public void Add(ResourcePoolBase<ResourceItemBase> pool)   { pool.Add(this); }}

Doesn't this work ?

And I don't understand what's so bad about doing it the other way round:
abstract class ResourcePoolBase<itemType> : NamedDataPool<itemType> where itemType : ResourceItemBase{   public void Add(itemType item)   { /* blahblah */ }}abstract class ResourceItemBase : INameable{ }// And later in code, instead of calling: item.Add(pool), call:pool.Add(item);

Which looks more logical to me.

Regards,
jods

##### Share on other sites
Quote:
 Original post by jodsDon't take it bad, but it really looks like a mess!

I know jods!
Quote:
 I don't understand why you need to make items generic in the first place ? You said: "the ResourceItemBase needs to know the pool type to take it as a parameter and be able to add itself".I don't think so. What about this:*** Source Snippet Removed ***Doesn't this work ?

Yea, I had it as in your lovely code snippet before I got into the mess with generics.

Right...sorry, I should probably have explained why I got into the mess better.
I now have ResourceItemBase and ResourcePoolBase as before the mess, and in the forms you put in your code snippet. That compiles without errors, but the trouble is when deriving.
I derive from ResourcePoolBase VideoResourcePoolBase. As you might expect, I want this to contain VideoResourceItemBase[s] rather than ResourceItemBase[s].

Here is a sample constructor from each:
protected ResourceItemBase(ResourcePoolBase<ResourceItemBase> resourcePool, string name){	if (resourcePool == null) throw new System.ArgumentNullException("resourcePool");	m_ResourcePool = resourcePool;	m_Name = name;	//Add this resource to the resource pool	m_ResourcePool.Add(this);}protected VideoResourceItemBase(VideoResourcePoolBase<VideoResourceItemBase> videoResourcePool, string name) : base(videoResourcePool, name){}

The problem is that VideoResourcePoolBase<VideoResourceItemBase> will simply not cast down to ResourcePoolBase<ResourceItemBase>. I can see why casting down the <VideoResourceItemBase> bit might be disallowed (as the VideoResourcePool wouldn't have type safety any more) but as I'm downcasting both together I think it should be fine.

Actually I just thought that I might be able to specify the type of the item as a generic parameter to the ResourceItemBase, rather than the pool's type (because I can define in the item ResourceItemBase<T>, the T would be it's derived type) as in the mess since I'm allowed to cast down the pool type...
I don't know if I'll have time to try that before I go away for 3 or 4 days..I have to go like right now...
But this might work!!

Thanks a lot :)

EDIT:

Right, I've tried my idea and now I have:
public abstract class ResourcePoolBase<T> : NamedDataPool<T> where T : ResourceItemBase<T>
and
public abstract class ResourceItemBase<T> : INameable where T : ResourceItemBase<T>

m_ResourcePool is defined as:
ResourcePoolBase<T> m_ResourcePool;

and the sample constructor:
protected ResourceItemBase(ResourcePoolBase<T> resourcePool, string name)
{
//removed other irrelevant stuff
//Add this resource to the resource pool
}

I get the error 'best overloaded match for ... has some invalid arguments:
Argument '1': cannot convert from 'DirectXEngines.ResourceItemBase<T>' to 'T''

What is T? T is constrained to ResourceItemBase<T>.

So basically that error is saying 'cannot convert from 'DirectXEngines.ResourceItemBase<T>' to 'DirectXEngines.ResourceItemBase<T>'

EDIT 2: Also, note that the two Ts are convertible (I didn’t get that compiler error saying that T must be convertible) because they both have the same constraints.

I think I need to inform Microsoft, as I'm sure one should be able to do such a thing...

[Edited by - DrGUI on July 21, 2005 4:58:21 PM]

##### Share on other sites
wait a second... In your EDIT example, isn't that a recursive definition ?

public abstract class ResourceItemBase<T> : INameable where T : ResourceItemBase<T>

I can't see any sensible way for this to work...

Now, in your original example, I'm surprised that your VideoResourcePoolBase is generic (?!). What is its definition exactly ? I was expecting this:

class VideoResourcePoolBase : ResourcePoolBase<VideoResourceItemBase>
{}

which is not generic, and should work.

Good luck,
jods

##### Share on other sites
Thanks again...but I need VideoResourcePoolBase to be generic because I make it non-generic when I derive the specific resource pools like TexturePool : VideoResourcePoolBase<Texture> is what I need.

I got a quick response from the .NET team - haven't had time to read yet but I'm going to be kicked off the internet in a min so I'll just paste it here:

Quote:

[Edited by - DrGUI on July 22, 2005 12:01:17 PM]

• ### What is your GameDev Story?

In 2019 we are celebrating 20 years of GameDev.net! Share your GameDev Story with us.

• 28
• 16
• 10
• 10
• 11
• ### Forum Statistics

• Total Topics
634111
• Total Posts
3015573
×