0

UPDATE:

Thanks to some help it seems to be a bug with Unity's compiler as it doesn't happen outside of Unity. I am currently submitting a bug report and I'll try and find a work around.


I originally posted this to reddit but I think I will need all the help I can get. Here is it copied over:

Not sure how it has come to this, but in order to maintain maximum extendability I have had to use all this techniques. In short, this works

ICombatEffect<IEffectReturn> com = new TackleEffectBase(this);

but when I try this

ICombatEffect<IEffectReturn>[] EffectsArra = ICombatEffect<IEffectReturn>[]{new TackleEffectBase(this);}

or this

List< ICombatEffect<IEffectReturn>> EffectsList = new List< ICombatEffect<IEffectReturn>>{new TackleEffectBase(this)}

I get an ArrayTypeMismatchException.

Now for the details: (although I've condensed this a lot) p

ublic interface ICombatEffect<out T> where T : IEffectReturn
    {
        T Effect(CombatProcessor combat);
    }

public abstract class EffectTemplate<T1> : ICombatEffect<T1> where T1 : IEffectReturn
    {
        public abstract T1 Effect(CombatProcessor combat);
    }

public abstract class DamageBaseTemplate : EffectTemplate<DamageBaseModifier>
    {}

DamageBaseModifier : IEffectReturn

public class TackleEffectBase : DamageBaseTemplate

I've left out all of the functional stuff so I can let the types do the talking. The premise is that I each ICombatEffect has an Effect Method. The Effect method must always have a return type that implements IEffectReturn interface. I need to preserve the return type of each ICombatEffect as it is used for sorting later.

Since I have quite a lot of functional code, I've put in the abstract class EffectTemplate. I've read a lot about this sort of style and the trick is to make the interface non-generic. I do not have that luxury unfortunately as sometimes I will not be using the template. So I have set up the interface with a covariant generic type. The abstract class sort of has its generic type linked so they will be the same. This took me a bloody long time to figure out and I was pretty disappointing when I couldn't get it to run today.

I'm no expert on generics but here is my theory on why I can create a single instance but not add that to a collection. When you declare the single instance it goes through and sets all the generics to the instance's type. For a collection, you can't really make its generics concrete, they are only there to see if it slots in.

I'm pretty ok with tearing this down for a better solution as long as it fulfills my needs, but I'm pretty darn curious about this solution. I thought myself so clever when I got all these cascading generic types to work, but alas.

  • 2
    The list line complies just fine. Same for array if you fix the syntax errors `ICombatEffect[] EffectsArra = { new TackleEffectBase(this) };` – Ivan Stoev Jul 02 '16 at 06:13
  • It compiles for me too, but whenever I try to add something to the array I get an error. Sorry if that wasn't clear. – Cupboard Horsington Jul 02 '16 at 06:37
  • 3
    You cannot "add" to array. But you can add to list and it works for me. I think you should edit your question and provide [mcve]. – Ivan Stoev Jul 02 '16 at 06:47
  • This is very bizarre on many levels. – Fattie Jul 02 '16 at 12:54
  • FTR I would encourage you to read this... http://stackoverflow.com/a/38145855/294884 – Fattie Jul 02 '16 at 12:59
  • Thanks Joe but I don't understand how this relates to what we are discussing here, I must have missed something. I'm not dealing with game objects at all. If you are referring to a component based design opposed to inheritance, don't worry that is one of my main focuses. – Cupboard Horsington Jul 02 '16 at 15:17

0 Answers0