I have the a "Transfer" method that is designed to take an amount from one pile to another. Now obviously you don't want to be transferring things into piles of the wrong type.
using System.Collections;
public class Pile
{
public int Amount;
public int GetAmount { get { return Amount; } }
}
public static class PileHelper
{
public static void Transfer<T>(this T from, T to, int amount) where T : Pile
{
from.Amount -= amount;
to.Amount += amount;
//Debug.Log(amount + " " + typeof(T).ToString() + " sent.");
}
}
//example
public class Meat : Pile
{
}
public class Fruit : Pile
{
}
public class Example
{
public void Test()
{
var meat = new Meat();
var fruit = new Fruit();
var pile = new Pile();
meat.Transfer(pile, 1); //correctly compiles, can transfer to a less derived type
meat.Transfer(fruit,1); //correctly does not compile, different types
pile.Transfer(meat, 1); //incorrectly compiles, should not compile because transfering to a more derived type
}
}
I want to set up my generic arguments in such a way that "pile" cannot transfer to "meat". The type T is defined by the arguments, and when one is derived from the other it takes the least derived. I want to force it to take the first argument and give a compiler error if the second argument is invalid.
One solution I can think of is this, but it seems a bit crude. (haven't tested it) I would prefer compiler errors rather than runtime exceptions.
public static void Transfer<T>(this T from, Pile to, int amount) where T : Pile
{
if(!(to is T)){ throw new Exception();}
from.Amount -= amount;
to.Amount += amount;
//Debug.Log(amount + " " + typeof(T).ToString() + " sent.");
}
I'm going to have to sadly exclude covariance and contravariance as Unity3D has all sorts of runtime errors when using them. Its a know problem about passing complex pointers.