C#铸造奇怪
我在奇怪的情况下玩弄泛型,我遇到了一个奇怪的情况,其“解决方案”,我不希望工作。这里是有问题的代码...C#铸造奇怪
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
}
}
}
对不起,离开了这一点。
我开始用你的代码(或多或少)和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是从别的地方来了。
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的,你总是可以沿着工厂方法传递既然你正在使用的构造函数代码,它是很清楚,为什么你需要一个投至T (以及为什么传递工厂方法,正如我上面所建议的,这是一个好主意)。如果你想限制TournamentGame只参加锦标赛球队(你的代码是),那么请提供一个直接参加锦标赛团队的构造函数。如果没有,那么你不应该在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>());
奇怪的是,它会说演员是没有必要的。 4.0上的VS2010给出了“无法从TournamentTeam
我发布的第一个代码示例使用VS2010在4.0上进行编译。也许你的'TournamentGame'类的构造函数是不同的?您没有发布该部分。 – 2012-03-11 06:19:53
你是对的,让我给构造函数。在问题中...... – aaronburro 2012-03-11 06:22:24
如果我理解你是正确的,你不能在泛型的构造函数中指定这样的约束。 Here is some thoughts与您的问题相关。
有趣的阅读。他似乎在研究我一直在处理的相同问题。 – aaronburro 2012-03-11 05:36:36
也许我错了,可是我什么也看不到一般在这种方法中,只是一个非常使用常规类型的尴尬的方式。\ – 2012-03-11 05:06:05
好吧,我的使用泛型的很多原因在此代码示例中是隐藏的,因为泛型将用于正在使用的对象类型中,而不是在此特定代码中。该函数是另一个需要泛型的静态函数的辅助函数。但是,我更多地在回归声明中询问演员,如果这是一个好的或不好的主意。 – aaronburro 2012-03-11 05:36:02
尽管如此,你是对的。这个问题与泛型没有任何关系,我意识到在我点击提交按钮之前,实际上改变了标题,但忘了删除泛型标记。现在删除该标签。 – aaronburro 2012-03-11 05:40:00