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