所以我必须设计一个适用于配对对象集合的类。对象之间存在一对一的映射。我希望类的客户端在使用我的类之前已经建立了这个映射。
我的问题是,让班级用户给我这些信息的最佳方法是什么?
是否要求收集这样的一对?
MyClass(IEnumerable<KeyValuePair<Object, Object>> objects)
或者像这样单独收藏?
MyClass(IEnumberable<Object> x, IEnumerable<Object> y)
或者还有其他选择吗?
我喜欢第一个,因为关系是明确的,我不喜欢它,因为它给客户带来了额外的工作。
我喜欢第二种,因为类型更原始,需要的工作量更少,我不喜欢它,因为映射不明确。我必须假设订单是正确的。
请注意?
答案 0 :(得分:10)
在.NET 4中,您应该使用Tuple<T1,T2>
。有关MSDN上Tuple课程的更多信息。
答案 1 :(得分:5)
如果您有权访问它,请使用Tuple<T, R>
。如果不这样做,只需编写自己的通用Tuple
或Pair
类。我会避免使用KeyValuePair
,因为它很冗长且与Dictionary
有关联。
答案 2 :(得分:5)
我更喜欢你提到的两个KeyValuePair,因为它更具表现力并保持对象之间的关系。
但我宁愿创建一个包含对你的对的引用的类。在我看来,这更具可读性,创建一个额外的类或结构来表达你的实际行为永远不会伤害。
(伪代码)
class MyPair
{
public TypeA One;
public TypeB Two;
}
MyClass(IEnumerable<MyPair> objects)
在某些答案中提到了Tuple<,>
,它与KeyValuePair一样可读,但更灵活,因为它可以包含两个以上的参数。
[编辑 - 在睡个好觉后更深入了解元组/课程]
答案 3 :(得分:1)
第一个是我首选的方法,因为一个序列可能比另一个序列长,而第二个序列不能保持所需的1:1映射。
答案 4 :(得分:1)
在我看来,第二个选项为您和客户提供了更多工作要做。第一种选择是更安全,更难出错。我会选择第一个选项或类似的东西。
答案 5 :(得分:1)
我当然更喜欢第一个。正如你所说,显式中的相关性,并且它比你需要测试两个集合具有相同长度的第二个更不容易出错。当然,提供/两种/方式实际上可能是合适的,这取决于您正在构建的实际课程。
有一件事,如果你使用.NET 4.0,我建议使用Tuple<T1, T2>
而不是KeyValuePair。
答案 6 :(得分:0)
我认为你必须选择1.必须有明确的关系或者你只是在寻找麻烦。
答案 7 :(得分:0)
我会使用第二个版本(因为它更简单)+评论+静态/动态检查。如果您可以使用代码协定,请尝试确保集合的长度相同,而不是null。如果没有,请对Debug.Assert
以及if ... throw ArgumentException
执行相同操作。或者,您可以创建包含该对的自己的对象,但是如果您想对该对的成员使用泛型则会变得更难。此外,当您创建一个要存储在容器中的对象时,您必须正确实现GetHashCode
,Equals
等。第一个“Effective C#”书中有一个项目。< / p>
作为一般规则,我不想过度设计方法签名。
答案 8 :(得分:0)
我通常提供两者,KeyValuePair构造函数委托给2-arg构造函数。两全其美。
答案 9 :(得分:0)
我喜欢第一种方法,原因有两个。
如果他们将他们的关系存储在词典中&lt;&gt;对象已经存在,他们可以按原样交出字典 - 无需额外的代码。
如果他们使用自己的自定义存储,那么使用yield语句在IEnumerable中为您提供KeyValuePairs非常简单
这样的事情:
IEnumerable<KeyValuePair<Object,Object>> GetMappedPairs()
{
foreach( var pair in _myCustomData )
{
yield return new KeyValuePair{Key = pair.ID, Value = pair.Data};
}
}
使用您的方法的开发人员不容易理解选项编号2,因此需要文档和注释来解释如何使用它。
顺便提一下,通过将您的方法声明为通用而非硬编码KeyValuePair
,您可能会得到最好的服务。MyClass<TKey,TValue>( IEnumerable<KeyValuePair<TKey,TValue>> pairs );
答案 10 :(得分:0)
可能值得考虑为什么要公开一个可枚举的原因。您可以使用Add(对象a,对象b)方法完全隐藏处理对的内部方式。然后,客户可以设置他们自己的方式来添加关系,无论是设置还是单独。
当然,如果你仍然需要一个采用可枚举的方法,那么第一个选项可能是最好的:显式关系。但是你考虑使用或者使用Tuple或Pair类型来代替KeyValuePair,假设它们之间的关系不是Value to Value性质之一。
答案 11 :(得分:0)
现在如果你做了 this 这样的事情怎么办?
// The client can choose to put together an IEnumerable<...> by hand...
public MyClass(IEnumerable<KeyValuePair<object, object>> pairs)
{
// actual code that does something with the data pairs
}
// OR the client can pass whatever the heck he/she wants, as long as
// some method for selecting the Xs and Ys from the enumerable data is provided.
// (Sorry about the code mangling, by the way -- just avoiding overflow.)
public static MyClass Create<T>
(IEnumerable<T> source, Func<T, object> xSelector, Func<T, object> ySelector)
{
var pairs = source
.Select(
val => new KeyValuePair<object, object>(
xSelector(val),
ySelector(val)
)
);
return new MyClass(pairs);
}
这将允许客户编写如下代码:
// totally hypothetical example
var stockReturns = StockReturns.Create(prices, p => p.Close, p => p.PrevClose);