Referring to C# Generics agnostically

I have a class with a generic modifier:

public abstract class Entity<T> : MonoBehavior where T:Weapon {
 public T weapon

and some subclasses of it:

//can carry any type of weapon
public abstract class VehicleEntity : Entity<Weapon> {
...
//can only carry SmallArms, a subclass of Weapon
public abstract class InfantryEntity : Entity<SmallArms> {

later on I want some other class to reference an Entity. What T is doesn’t matter to this class. I though I could signify that by using <?>:

public class SomeClass : MonoBehavior {
  Entity<?> entity;

but I get an error:
error CS1519: Unexpected symbol `<’ in class, struct, or interface member declaration

So maybe that was Java or something else where that worked. Is it possible to do this some other way in C#?

If not, I guess I could do this:

public abstract class Entity : MonoBehavior {
...
public abstract class EntityWithWeapon<T> : Entity where T:Weapon {
 public T weapon
...

and then extend off of EntityWithWeapon, but refer to Entity in most places. Not as nice though.

//EDIT - in Java <?> are called wildcards. In C# they don’t exist. Any suggestions on how to handle this?

There is no wildcard generic. If you make an instance of a class the generic must defined out. The idea is that generics are always typesafe, otherwise you wouldn’t need generics, you could just bomb around with Object references.

Thats what you will need to do here too, declare it as <System.Object>. But as mentioned, this makes the generic basically totally pointless right from the start.
So better get a proper baseclase in place which all “entities” base on thats not as open and undefined as Object, for your case this seems to be Weapon.

As dreamora suggested, you can create another base class of Entity that’s non-generic. Here’s some samples to get you going, may not be the best examples but just whipped them off:

If you need to grab a reference to the weapon object, you’ll need to have it exposed as a base “object”:

public abstract class Entity : MonoBehavior
{
	private object m_UntypedWeapon;
	public virtual object UntypedWeapon
	{
		get
		{
			return m_UntypedWeapon;
		}
		protected set
		{
			m_UntypedWeapon = value;
		}
	}
}

public abstract class Entity<T> : Entity where T:Weapon 
{
	public override object UntypedWeapon
	{
		get
		{
			return base.UntypedWeapon;
		}
		protected set
		{
			if (value is T)
			{
				base.UntypedWeapon = value;
			}
			throw new System.InvalidCastException();
		}	
	}
	public T Weapon
	{
		get
		{
			return (T)base.UntypedWeapon;
		}
		set
		{
			base.UntypedWeapon = value;
		}
	}
}

Or if your weapons are always of “Weapon” type:

public abstract class Entity : MonoBehavior
{
	private Weapon m_UntypedWeapon;
	public virtual Weapon UntypedWeapon
	{
		get
		{
			return m_UntypedWeapon;
		}
		protected set
		{
			m_UntypedWeapon = value;
		}
	}
}

public abstract class Entity<T> : Entity where T:Weapon 
{
	public override Weapon UntypedWeapon
	{
		get
		{
			return base.UntypedWeapon;
		}
		protected set
		{
			if (value is T)
			{
				base.UntypedWeapon = value;
			}
			throw new System.InvalidCastException();
		}	
	}
	public T Weapon
	{
		get
		{
			return (T)base.UntypedWeapon;
		}
		set
		{
			base.UntypedWeapon = value;
		}
	}
}

Or if you don’t need access to that generically typed Weapon, then it’s even simpler:

public abstract class Entity : MonoBehavior
{

}

public abstract class Entity<T> : Entity where T:Weapon 
{
	public T Weapon;
}

Then wherever you need to work with your concept of Entity<?>, you would instead just use Entity.

Thanks, I’ve implemented that, it’s the simple case so it was pretty straightforward. Generally it works great but I keep getting hung up by the fact that the generic arg doesn’t seem to be cast from a subclass up. I’ve worked around it but it is annoying. Example:

public class Entity : MonoBehavior {
...
public class EntityArmed<T> : Entity where T : Weapon {
... 
public class EntityFlock : Entity<Boid> { //Boid is a subclass of Weapon
...
//then later
void SomeMethod(EntityArmed<Weapon> aweapon) {
... 
//this doesn't work, though one would hope it would:
// since EntityFlock is a subclass of EntityArmed
// and Boid is a subclass of Weapon
EntityFlock myFlock;
SomeMethod((EntityArmed<Weapon>)myFlock);

Assets/Game/Flock/EntityFlock.cs(23,44): error CS0030: Cannot convert type EntityFlock' to EntityArmed’

and without the cast it doesn’t recognize the signature of the method. Quite a gotcha.

See my second example, pakfront. It solves this issue for you.

Thanks again, I wrapped my head around it and got it to work as you demonstrated. Still not fond of the gyrations this aspect of generics causes, but it’s still worth using them despite this.