【发布时间】:2019-01-09 02:48:22
【问题描述】:
假设我有一个“动物园”移动应用。它从在线服务器获取“动物”并将它们存储在本地数据库中。
Class Animal
Class Bird : Animal
Class Fish : Animal
Class Pelican : Bird
Class Penguin : Bird
所以我创建了一个具有以下功能的类 GetAnimalsFromServerService。
public Task<Animal[]> GetAnimalsFromServer<T>() where T : Animal, new() {
if (typeof(T) == typeof(Bird)) {
return GetBirdsFromServer<T>();
} else if (typeof (T) == typeof(Fish)){
return GetFishFromServer<T>();
}
}
private Task<Bird[]> GetBirdsFromServer<T>() where T : Bird, new() {
// Bird specific functionality here.
if (typeof(T) == typeof(Pelican)) {
return _serverConnection.GetPelicansFromServer();
} else if (typeof (T) == typeof(Penguin)){
return _serverConnection.GetPenguinsFromServer();
}
}
这不会编译,因为 T 是“Animal”类型而不是“Bird”类型(并且 GetBirdsFromServer 需要“Bird”类型)。
自从“if(typeof(T) == typeof(Bird))”检查后我知道 T 是 Bird 类型,有没有办法将 T 转换为 Bird?
编辑: 根据要求,以下行无法编译
return GetBirdsFromServer<T>();
错误是:
类型“T”不能用作泛型类型或方法“GetBirdsFromServer()”中的类型参数“T”。没有从 'T' 到 'Bird' 的隐式引用转换
编辑 2: 好的,我想我明白为什么这不起作用了。基本上我最初的问题是“是否有一个我不知道的关键字可以让我做相当于:
return GetBirdsFromServer<(T as Bird)>();
但这是不可能的,因为“as”关键字本质上是在告诉计算机“哟,这个物体是一只鸟,相信我”。然后,如果它不是一只鸟,计算机可能会像“你撒谎了,那我就把对象设置为空”。
但在这种情况下,计算机并未考虑对象。因此,当您撒谎时,计算机就像“哦,便便,这不是对象,我该怎么办?”。因此,由于单独的行并不能保证 T 是 Bird,因此无法进行某种类型的强制转换或等效。
【问题讨论】:
-
你有一个带有类型参数的抽象类吗?
-
如果泛型成员只在类型上起作用,那么它是毫无意义的。这是您必须区分类型的时候。事实上,泛型成员不应该知道任何可能匹配泛型约束的可能类型。这就是通用约束的全部意义所在。话虽如此,您不应该使用通用方法,而应为每种可能的类型使用不同的方法。
-
如果你需要为每种类型做特定的事情,泛型是错误的工具。
-
您试图在这里混合两个概念 - 泛型和继承。不知道你是否理解。总之,不好。忘记泛型,专注于只使用类层次结构来解决这个问题。
-
重点是,
T是一种在编译时已知的类型。因此,当您知道编译时的时间时,您也可以只调用另一个方法。如果您使用GetAnimalFromServer<Penguin>而不是GetPenguinFromServer,则没有任何好处,是吗?无论如何,您都必须提供类型。显然,您想要的是从数据库中检索实体,而无需在编译时完全知道类型。在这种情况下,泛型是错误的工具。
标签: c# generics types parameters