Restricting arguments to less or equally derived types

Viewed 34

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.

2 Answers
Related