C # Странность - PullRequest
       17

C # Странность

0 голосов
/ 11 марта 2012

Я играю с дженериками в странных обстоятельствах, и я столкнулся со странной ситуацией, чье «решение» я не ожидаю, что сработает.Вот оскорбительный код ...

static TournamentGame<T, Y> make16Game<T, Y>(int gameId, int seed1, int seed2, List<Y> teams)
        where T : TournamentTeam<Y>
        where Y : Team
    {
        /*
         * bunch of code removed for clarity
         */

        // return that bad boy
        return new TournamentGame<T, Y>(gameId,
                                        (T)(new TournamentTeam<Y>(seed1, teams[seed1 - 1])),
                                        (T)(new TournamentTeam<Y>(seed2, teams[seed2 - 1])));
    }

Глядя на это, я не вижу, как это позволяет компилятор.Моя интуиция заключается в том, что я получу ошибку времени выполнения, если когда-нибудь вызову ее с T, отличным от TournamentTeam.Если я не добавлю приведение, я получу ошибку компиляции.Правильна ли моя интуиция?То, что я ЛЮБЛЮ, чтобы сделать, это установить ограничение, что T должен иметь конструктор, который принимает параметры String и Y, но это другая проблема.Я полагаю, я мог бы также использовать отражение, чтобы получить этот конструктор для T, но где в этом веселье?

В любом случае, мысли?

РЕДАКТИРОВАТЬ TournamentGame выглядит следующим образом:

public class TournamentGame<T, Y> : Game<T>
    where T : TournamentTeam<Y>
    where Y : Team
{
    public TournamentGame(int id, T t1, T t2, Region<T, Y> region = null)
        : base(id, t1, t2)
    { 
        // do your thang
    }
}

public class Game<T>
    where T : Team
{
    private T mTeam1 = null;

    private Game(int id)
    {
        // do your thang
    }

    public Game(int id, T t1, T t2)
        : this(id)
    {
        // do your thang
    }

    public T Team1
    {
        get 
        {
            // do your thang
        }
    }
 }

Извините, что пропустил это.

Ответы [ 2 ]

1 голос
/ 11 марта 2012

Я начал с вашего кода (более или менее), и резарпер сразу же сказал мне, что приведение к T не нужно:

public class Test
{
    static TournamentGame<T, Y> make16Game<T, Y>(int gameId, int seed1, int seed2, List<Y> teams)
        where T : TournamentTeam<Y>
        where Y : Team
    {
        return new TournamentGame<T, Y>(gameId, 
                                        new TournamentTeam<Y>(seed1, teams[seed1 - 1]),
                                        new TournamentTeam<Y>(seed2, teams[seed2 - 1]));
    }
}

internal class Team { }

internal class TournamentTeam<T> {
    public TournamentTeam(int seed1, Team team) {
        throw new NotImplementedException();
    }
}

internal class TournamentGame<T, Y> {
    public TournamentGame(int gameId, TournamentTeam<Y> tournamentTeam, TournamentTeam<Y> tournamentTeam1) {
        throw new NotImplementedException();
    }
}

Таким образом, потребность в приведении к Т приходит откуда-то еще. Если вам нужен определенный тип «конструктора» для T, вы всегда можете передать фабричный метод:

    static TournamentGame<T, Y> make16Game<T, Y>(int gameId, int seed1, int seed2, Func<int, Y, T> tournamentTeamFactory, List<Y> teams)
        where T : TournamentTeam<Y>
        where Y : Team
    {
        return new TournamentGame<T, Y>(gameId, 
            tournamentTeamFactory(seed1, teams[seed1 - 1]), 
            tournamentTeamFactory(seed2, teams[seed2 - 1]));
    }

РЕДАКТИРОВАТЬ: Учитывая код конструктора, который вы используете, ясно, зачем вам приведение к T (и почему передача фабричного метода, как я предлагаю выше, хорошая идея). Если вы хотите ограничить TournamentGame только использованием TournamentTeams (что ваш код эффективно делает), тогда предоставьте конструктор, который напрямую принимает TournamentTeam. Если нет, то вам не следует создавать TournamentTeams в вашей функции make16Game. Представьте себе следующее:

public class AllStarTeam<T> : TournamentTeam<T> where T : Team
{
    public AllStarTeam(int seed1, Team team) : base(seed1, team)
    {
        throw new NotImplementedException();
    }
}

Затем это компилируется, но выдает исключение времени выполнения (Плохая вещь):

Test.make16Game<AllStarTeam<T>, T>(5, 5, 5, new List<T>());
1 голос
/ 11 марта 2012

Если я вас правильно понял, вы не можете указать такие ограничения на конструктор в обобщениях. Вот некоторые мысли , связанные с вашим вопросом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...