C#铸造古怪

时间:2012-03-11 04:38:40

标签: c# casting

我在一个奇怪的环境中玩弄仿制药,我遇到了一个奇怪的情况,其“解决方案”我不希望工作。这是有问题的代码......

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必须有一个带StringY参数的构造函数,但这是另一个问题。我想我也可以使用反射来获取T的构造函数,但那里的乐趣在哪里?

无论如何,想法?

EDIT 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 个答案:

答案 0 :(得分:1)

如果我理解正确,则无法在泛型中对构造函数指定此类约束。 Here is some thoughts与您的问题有关。

答案 1 :(得分:1)

我开始使用你的代码(或多或少)和resharper立即告诉我,对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的演员阵容来自其他地方。如果你想要一个特定类型的“构造函数”用于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的构造函数。如果没有,那么你不应该在make16Game函数中创建TournamentTeams。想象一下:

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>());