none
Круговые ссылки в генериках RRS feed

  • Общие обсуждения

  • У меня прога на C# и есть съедаемые объекты (растения и травоядные) и едящие объекты(травоядные и хищники). Хочу сделать такую схему классов:

        // я съедаемый животным, у которого жертва я сам
        public interface IEatableBy<TEater>
            where TEater : Animal<IEatableBy<TEater>>
        {
            void BeEatenBy(TEater animal);
        }
        public abstract class Animal<TVictim>
                //моя жертва съедаема мной самим
                where TVictim : IEatableBy<Animal<TVictim>>
        {
            /// <summary>
            /// жертвы
            /// </summary>
            protected HashSet<TVictim> Victims;
        }
        public class Plant : IEatableBy<Herbivore>
        {
                public void BeEatenBy(Herbivore animal)
                {
                }
        }
        public class Predator : Animal<Herbivore>
        { }
        public class Herbivore : Animal<Plant>, IEatableBy<Predator>
        {
                public void BeEatenBy(Predator animal)
                {
                }
        }

    Проблема в том, что при такой схеме компилер выдает такие ошибки:
    1) на строке
    public interface IEatableBy<TEater>
    подчеркивает TEater и пишет:

    Тип "Assets.IEatableBy<TEater>" не может быть использован как параметр типа "TVictim" в универсальном типе или методе "Animal<TVictim>". Нет преобразования неявной ссылки из "Assets.IEatableBy<TEater>" в "Assets.IEatableBy<Animal<Assets.IEatableBy<TEater>>>"

    2) на строке

       public abstract class Animal<TVictim> : MonoBehaviour
    подчеркивает TVictim и пишет:

    Тип "Animal<TVictim>" не может быть использован как параметр типа "TEater" в универсальном типе или методе "IEatableBy<TEater>". Нет преобразования неявной ссылки из "Animal<TVictim>" в "Animal<Assets.IEatableBy<Animal<TVictim>>>"

    Мои вопросы:
    1) Почему появляются такие ошибки при компиляции? Моя схема со всеми ее констрейнтами нарушает какой-то здравый смысл или логику (тогда каким образом оно нарушается)?
    2) Если моя схема не нарушает здравый смысл, то почему не компилится? Недостаток компилера сишарпа? То есть теоретически в будущем она может начать компилиться?
    3) Как правильно реализовать этот мой замысел, но чтобы оно компилилось?

    На третий вопрос многие ответят: "зачем делать эту лапшу и генериков и констрейнтов, ничего в ней не понятно. Избавься от них и все заработает". Но почему я тут хочу использовать именно генерики и именно такие ограничения? Очевидно, чтобы Хищники могли есть только травоядных, а травоядные только растения. И чтобы в производном классе "Травоядные" проперти

    protected HashSet<TVictim> Victims;
    содержало только растения и метод
     public void BeEatenBy(Predator animal)
    при оверрайде принимал параметром только хищников. И по аналогии со всеми другими классами.
    2 февраля 2018 г. 17:29