C# 如果你不是';如果您不想将集合返回给调用者,您应该如何将数据集合返回给调用者?

C# 如果你不是';如果您不想将集合返回给调用者,您应该如何将数据集合返回给调用者?,c#,.net,collections,C#,.net,Collections,我正在编写一个方法,用于返回一个充满配置键和值的字典。构建这个字典的方法是动态的,所以我需要将这组键和值作为一个集合返回(可能是IDictionary)。在我的各种阅读资料中(目前我还不知道来源),关于从方法调用返回集合类型的普遍共识是而不是 我理解这项政策的原因,我倾向于同意,但在这种情况下,我看不到其他选择。这是我的问题:在遵循这个原则的同时,有没有一种方法可以将这些数据返回给调用者 编辑:我听说不允许这种行为的原因是,客户机要使用(但不修改)的集合或字典类型暴露了太多行为,使调用方产生可以

我正在编写一个方法,用于返回一个充满配置键和值的字典。构建这个字典的方法是动态的,所以我需要将这组键和值作为一个集合返回(可能是
IDictionary
)。在我的各种阅读资料中(目前我还不知道来源),关于从方法调用返回集合类型的普遍共识是而不是

我理解这项政策的原因,我倾向于同意,但在这种情况下,我看不到其他选择。这是我的问题:在遵循这个原则的同时,有没有一种方法可以将这些数据返回给调用者

编辑:我听说不允许这种行为的原因是,客户机要使用(但不修改)的集合或字典类型暴露了太多行为,使调用方产生可以修改该类型的错觉。例如,Dictionary有Add和Remove方法,以及一个可变索引器。如果字典中的值是只读的,那么这些方法充其量是多余的。如果内部藏品暴露在外,且藏品的“所有人”没有预料到外部来源对藏品的更改,则可能造成进一步的损害

我还听到了其他一些原因,但我一时想不起来——这些是我目前处境中最重要的原因

编辑:进一步澄清:我遇到的问题是我正在构建一个API,因此我无法控制调用此函数的客户端。克隆字典不是一个问题,但我正在努力保持我的API尽可能干净。使用Add和Remove等方法返回字典意味着可以或应该修改集合,但事实并非如此。这里的修改是没有意义的,因此我不想通过返回类型的接口公开该功能的承诺


解析:为了满足我对干净API的需求,我将编写一个自定义字典类,该类不公开突变方法Add和Remove或set indexer。这种类型不会实现
IDictionary
,但我将编写一个方法
ToDictionary
,该方法将返回
IDictionary
中的数据。它将实现
IEnumerable
,以便访问可枚举上的标准LINQ操作。现在我只需要自定义字典类型的名称…=)谢谢大家

关于回归的普遍共识 方法调用的集合类型为 不可以

我第一次听到这个,对我来说这似乎是一个愚蠢的限制

我理解其中的原因 政策

那他们是谁

编辑:
您反对返回集合的原因是特定的潜在问题,这些问题可以是特定的地址(通过返回只读包装),而不必对返回集合进行全面限制。但据我所知,集合实际上是由方法构建的——在这种情况下,调用方所做的更改不会影响任何其他内容,因此您不必担心,您也不应该过分限制调用方应该如何处理专门为他创建的对象。

我从未听过这个建议。如果做得不好,可能会出现线程安全问题,但如果需要,可以解决这个问题。

请查看ReadOnlyCollection()以了解此问题。将返回类型和上一条语句更改为

return new ReadOnlyCollection(whateverYouWereReturningBefore);

我通常返回一个数据数组和一个集合类型。例如,在C#中,许多集合实现了.toArray()方法,而对于那个些并没有实现的集合,可以使用lambdas检索数组

编辑

看到你对“不退款不退货”回答的评论。如果要返回字典,数组可能不适合您。在这种情况下,我建议返回一个接口,而不是一个具体的实现

在C#中(例如):

公共IDictionary MyMethod()
{
Dictionary myDictionary=新字典();
//在这里做事
返回myDictionary;
}
编辑2

您可能需要实现自己的只读字典类,并在必要的方法中抛出异常以防止添加等

在C#(同样,例如)(不是一个完整的解决方案)中:

公共类只读词典:IDictionary { 私人词典; 公共只读词典(IDictionary innerDictionary) { 这个。_innerDictionary=innerDictionary; } 公共无效添加(TKey键,TValue值) { 抛出新的NotImplementedException(); } 公用门移除(TKey) { 抛出新的NotImplementedException(); } 公共作废添加(KeyValuePair项) { 抛出新的NotImplementedException(); } 公共空间清除() { 抛出新的NotImplementedException(); } 公共图书馆是只读的 { 获取{return true;} } 公共布尔删除(KeyValuePair项) { 抛出新的NotImplementedException(); } 公共IEnumerator GetEnumerator() { 返回_innerDictionary.GetEnumerator(); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { 返回_innerDictionary.GetEnumerator(); } }
在我看来,如果更改返回的集合可能产生副作用,则返回集合只是一个问题,例如,多个函数可用于同一集合

如果您只是创建集合,而不是通过返回集合来公开类中的数据,我认为只返回字典是可以的

如果集合在代码中的其他位置使用,则返回
public IDictionary<string, object> MyMethod()
{
    Dictionary<string, object> myDictionary = new Dictionary<string, object>();

    // do stuff here

    return myDictionary;
}
public class ReadOnlyDictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
    private IDictionary<TKey, TValue> _innerDictionary;

    public ReadOnlyDictionary(IDictionary<TKey, TValue> innerDictionary)
    {
        this._innerDictionary = innerDictionary;
    }

    public void Add(TKey key, TValue value)
    {
        throw new NotImplementedException();
    }

    public bool Remove(TKey key)
    {
        throw new NotImplementedException();
    }

    public void Add(KeyValuePair<TKey, TValue> item)
    {
        throw new NotImplementedException();
    }

    public void Clear()
    {
        throw new NotImplementedException();
    }

    public bool IsReadOnly
    {
        get { return true; }
    }

    public bool Remove(KeyValuePair<TKey, TValue> item)
    {
        throw new NotImplementedException();
    }

    public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
    {
        return _innerDictionary.GetEnumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return _innerDictionary.GetEnumerator();
    }
}
Customer myCustomer = Database.GetCustomer("Fred Smith"); Customer myCustomer = new Customer; Database.LoadCustomer(myCustomer, "Fred Smith");