成对请求​​对象的最直观的方法是什么?

时间:2010-07-12 19:27:43

标签: c# usability

所以我必须设计一个适用于配对对象集合的类。对象之间存在一对一的映射。我希望类的客户端在使用我的类之前已经建立了这个映射。

我的问题是,让班级用户给我这些信息的最佳方法是什么?

是否要求收集这样的一对?

MyClass(IEnumerable<KeyValuePair<Object, Object>> objects)

或者像这样单独收藏?

MyClass(IEnumberable<Object> x, IEnumerable<Object> y)

或者还有其他选择吗?

我喜欢第一个,因为关系是明确的,我不喜欢它,因为它给客户带来了额外的工作。

我喜欢第二种,因为类型更原始,需要的工作量更少,我不喜欢它,因为映射不明确。我必须假设订单是正确的。

请注意?

12 个答案:

答案 0 :(得分:10)

在.NET 4中,您应该使用Tuple<T1,T2>。有关MSDN上Tuple课程的更多信息。

答案 1 :(得分:5)

如果您有权访问它,请使用Tuple<T, R>。如果不这样做,只需编写自己的通用TuplePair类。我会避免使用KeyValuePair,因为它很冗长且与Dictionary有关联。

答案 2 :(得分:5)

我更喜欢你提到的两个KeyValuePair,因为它更具表现力并保持对象之间的关系。

但我宁愿创建一个包含对你的对的引用的类。在我看来,这更具可读性,创建一个额外的类或结构来表达你的实际行为永远不会伤害。

(伪代码)

class MyPair
{
    public TypeA One;
    public TypeB Two;
}

MyClass(IEnumerable<MyPair> objects)

在某些答案中提到了Tuple<,>,它与KeyValuePair一样可读,但更灵活,因为它可以包含两个以上的参数。

[编辑 - 在睡个好觉后更深入了解元组/课程]

To Tuple or Not To Tuple

答案 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执行相同操作。或者,您可以创建包含该对的自己的对象,但是如果您想对该对的成员使用泛型则会变得更难。此外,当您创建一个要存储在容器中的对象时,您必须正确实现GetHashCodeEquals等。第一个“Effective C#”书中有一个项目。< / p>

作为一般规则,我不想过度设计方法签名。

答案 8 :(得分:0)

我通常提供两者,KeyValuePair构造函数委托给2-arg构造函数。两全其美。

答案 9 :(得分:0)

我喜欢第一种方法,原因有两个。

  1. 如果他们将他们的关系存储在词典中&lt;&gt;对象已经存在,他们可以按原样交出字典 - 无需额外的代码。

  2. 如果他们使用自己的自定义存储,那么使用yield语句在IEnumerable中为您提供KeyValuePairs非常简单

  3. 这样的事情:

    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);