【发布时间】:2011-01-03 03:55:47
【问题描述】:
我是从 Java 背景开始使用 C# 的,并且不断遇到与泛型相同的问题,而这些问题在 Java 中很容易解决。
给定类:
interface IUntypedField { }
class Field<TValue> : IUntypedField { }
interface IFieldMap
{
void Put<TValue>(Field<TValue> field, TValue value);
TValue Get<TValue>(Field<TValue> field);
}
我想写一些类似的东西:
class MapCopier
{
void Copy(IEnumerable<IUntypedField> fields, IFieldMap from, IFieldMap to)
{
foreach (var field in fields)
Copy(field, from, to); // <-- clearly doesn't compile as field is IUntypedField not Field
}
void Copy<TValue>(Field<TValue> field, IFieldMap from, IFieldMap to)
{
to.Put(field, from.Get(field));
}
}
在 Java 中,这很容易解决,因为字段集合是 Iterable<Field<?>>,您可以直接调用 Copy(Field, IFieldMap, IFieldMap)。
在 C# 中,我发现自己对 TValue 的所有可能值进行了切换/转换(这闻起来很可怕,必须为您添加的每种类型添加一个案例显然是一个等待发生的错误,并且只有当集合类型是有限的):
foreach (var field in fields)
{
switch (field.Type) // added an enum to track the type of Field's parameterised type
{
case Type.Int: Copy((Field<int>)field, from, to); break;
case Type.Long: Copy((Field<long>)field, from, to); break;
...
}
}
我有时会做的另一个选择是将功能移到 Field 类中,这又很臭。这不是该领域的责任。至少这避免了巨大的开关:
interface IUntypedField { void Copy(IFieldMap from, IFieldMap to); }
class Field<TValue> : IUntypedField
{
void Copy(IFieldMap from, IFieldMap to)
{
to.Put(this, from.Get(this));
}
}
...
foreach (var field in fields)
field.Copy(from, to);
如果您可以编写多态扩展方法(即上面 IUntypedField 和 Field 中的 Copy 方法),那么您至少可以将代码保留在其职责所在的类中。
我是否遗漏了 C# 的某些功能,使这成为可能。还是有一些可以使用的功能模式?有什么想法吗?
(最后一件事,我目前被困在 .Net 3.5 上,因此无法使用任何协变/逆变,但仍然有兴趣知道它们将如何提供帮助(如果有的话)。
【问题讨论】:
-
我不确定我是否理解你的模式,你能提供一个 IFieldMap 的实现吗?
-
@Yads,实现在这里并不重要。正如 siride 所指出的那样,它将在内部将事物存储为对象并且必须进行转换,但就接口的消费者而言,它是放置和获取真实类型。
-
@Claus,该问题的答案假设用户想要使用同质列表(如 Danny Chen 的答案),这是一个不同的问题。
-
重点更多的是你发现在 Java 中更容易的原因是因为你使用了通配符。因此,他应该学习 Java 通配符的 C#“替代品”。