ehn*_*ark 17 c# generics wildcard
我正在阅读Codehua at Work中对Joshua Bloch的采访,他在Java 5中对泛型的介绍感到遗憾.他不喜欢具体的实现,主要是因为方差支持--Java的通配符 - 使得它不必要地复杂化.
据我所知,C#3没有像明确的,有界的通配符那样的东西,例如你不能声明一个接收Asset或任何Asset子类(void PriceBatch(Collection<? extends Asset> assets)在Java中?)的方法PriceBatch .
有谁知道为什么没有将通配符和边界添加到C#中?故意遗漏这些功能以使语言更简单,或者这是他们还没有实现的东西呢?
编辑:圣烟,Eric Lippert本人的评论!在阅读了他和Paul的深刻见解之后,我意识到至少支持上限,并且上面的例子可以转换为C#:
void PriceBatch<T>(ICollection<T> assets) where T : Asset
Run Code Online (Sandbox Code Playgroud)
另一方面,显然不支持下限,因为Eric在他的第二条评论中说,例如,可能没有办法直接将这个(有点人为的)Java代码转换为C#:
public class Asset {}
public class Derivative extends Asset {}
public class VanillaOption extends Derivative {}
public static <T extends Asset> void copyAssets(Collection<T> src, Collection<? super T> dst) {
for(T asset : src) dst.add(asset);
}
Collection<VanillaOption> src = new ArrayList<VanillaOption>();
[...]
Collection<Derivative> dst = new ArrayList<Derivative>();
[...]
copyAssets(src, dst);
Run Code Online (Sandbox Code Playgroud)
我对么?如果是这种情况,C#有上限而不是下限的特殊原因是什么?
Eri*_*ert 23
一个复杂的问题.
首先让我们考虑你的基本问题,"为什么这在C#中是非法的?"
class C<T> where T : Mammal {} // legal
class D<T> where Giraffe : T {} // illegal
Run Code Online (Sandbox Code Playgroud)
也就是说,泛型类型约束可以说"T必须是可以分配给Mammal类型的变量的任何引用类型",但不是"T必须是任何引用类型,其变量可以被赋予长颈鹿".为什么不同?
我不知道.那是在我加入C#团队之前很久.琐碎的答案是"因为CLR不支持它",但设计C#泛型的团队就是设计CLR泛型的团队,所以这真的不是一个解释.
我的猜测就是一如既往地支持必须设计,实施,测试,记录并运送给客户的功能; 没有人为这个功能做任何这些事情,因此它不在语言中.我没有看到提议的功能有一个巨大而引人注目的好处; 没有引人注目的好处的复杂功能往往会在这里削减.
但是,这是猜测.下次我碰巧和那些从事仿制药工作的人聊天 - 他们住在英格兰,不幸的是,不管他们是不是在我的大厅里,不幸的是 - 我会问.
至于你的具体例子,我认为保罗是正确的.您不需要下限约束来使其在C#中工作.你可以说:
void Copy<T, U>(Collection<T> src, Collection<U> dst) where T : U
{
foreach(T item in src) dst.Add(item);
}
Run Code Online (Sandbox Code Playgroud)
也就是说,将约束放在T上,而不是放在U上.
C#4引入了新功能,允许在泛型中进行协方差和逆变.
还有其他SO帖子更详细地讨论了这个问题: 如何在C#4.0中实现通用协方差和反差异?
新功能不会在所有类型中自动启用此功能,但有一种新语法允许开发人员指定通用参数是协变还是逆变.
C#4之前的C#版本具有与此类似的功能,因为它与委托和某些数组类型相关.关于委托,允许使用基本参数类型的委托.关于数组类型,我认为除非涉及拳击,否则它是有效的.也就是说,Customer数组可以是一个对象数组.但是,无法将一个int数组转换为对象数组.
.net已经相当于通配符,更符合逻辑命名的泛型类型约束,你可以做你所描述的没有问题
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
List<a> a = new List<a>();
List<b> b = new List<b>();
List<c> c = new List<c>();
test(a);
test(b);
test(c);
}
static void test<T>(List<T> a) where T : a
{
return;
}
}
class a
{
}
class b : a
{
}
class c : b
{
}
}
Run Code Online (Sandbox Code Playgroud)
例2
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
ICollection<VanillaOption> src = new List<VanillaOption>();
ICollection<Derivative> dst = new List<Derivative>();
copyAssets(src, dst);
}
public static void copyAssets<T,G>(ICollection<T> src, ICollection<G> dst) where T : G {
foreach(T asset in src)
dst.Add(asset);
}
}
public class Asset {}
public class Derivative : Asset {}
public class VanillaOption : Derivative {}
}
Run Code Online (Sandbox Code Playgroud)
此示例表示来自您在java中的示例的代码转换.
我不是真的能够回答实际的问题!
| 归档时间: |
|
| 查看次数: |
4135 次 |
| 最近记录: |