为什么Lookup在C#中是不可变的?
与Dictionary
不同,您无法通过逐个添加元素来构建Lookup
。 你碰巧知道原因吗?
Lookup
就像C ++中的multimap
一样; 为什么我们不能在C#中修改它? 如果我们真的不能,我们如何在C#中构建multimap
数据结构?
Lookup
和ILookup
作为LINQ的一部分引入,LINQ通常比框架的其他方面采用更多function方法。 我个人喜欢 Lookup
(至少是公开的)不可变的事实 – 我期待更多不可变的集合可用 。
如果要创建自己的多图数据结构,只需维护一个Dictionary
或类似的东西。 您可能需要查看我的Edulinq Lookup
实现以获取一些示例代码。
这是我写的一个实现
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; public class MultiLookup : ILookup { Dictionary> Contents = new Dictionary>(); public void Add(Key key, Value value) { if (!Contains(key)) { Contents[key]=new HashSet (); } Contents[key].Add(value); } public void Add(IEnumerable> items) { foreach (var item in items) { Add(item.Item1, item.Item2); } } public void Remove(Key key, Value value) { if (!Contains(key)) { return; } Contents[key].Remove(value); if (Contents[key].Count==0) { Contents.Remove(key); } } public void RemoveKey(Key key) { Contents.Remove(key); } public IEnumerable Keys { get { return Contents.Keys; } } public int Count { get { return Contents.Count; } } public bool Contains(Key key) { return Contents.ContainsKey(key); } private class Grouping : IGrouping { public MultiLookup _source; public Key _key; public Key Key { get { return _key; } } public static HashSet Empty = new HashSet (); public IEnumerator GetEnumerator() { if (!_source.Contains(_key)) { yield break; } else { foreach (var item in _source[_key]) { yield return item; } } } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return this.GetEnumerator(); } } public IEnumerator> GetEnumerator() { return (from p in Contents select new Grouping() { _key = p.Key, _source = this }).GetEnumerator(); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return this.GetEnumerator(); } public IEnumerable this[Key key] { get { return Contents[key]; } } }
和一个测试用例(可能不是详尽无遗)
using FluentAssertions; using System.Linq; using Xunit; public class MultiLookupSpec { MultiLookup Fixture = new MultiLookup(); [Fact] public void NewLookupShouldBeEmpty() { Fixture.Count.Should().Be(0); } [Fact] public void AddingANewValueToANonExistentKeyShouldCreateKeyAndAddValue() { Fixture.Add(0, "hello"); Fixture.Count.Should().Be(1); } [Fact] public void AddingMultipleValuesToAKeyShouldGenerateMultipleValues() { Fixture.Add(0, "hello"); Fixture.Add(0, "cat"); Fixture.Add(0, "dog"); Fixture[0].Should().BeEquivalentTo(new []{"hello", "cat", "dog"}); } [Fact] public void RemovingAllElementsOfKeyWillAlsoRemoveKey() { Fixture.Add(0, "hello"); Fixture.Add(0, "cat"); Fixture.Add(0, "dog"); Fixture.Remove(0, "dog"); Fixture.Remove(0, "cat"); Fixture.Remove(0, "hello"); Fixture.Contains(0).Should().Be(false); } [Fact] public void EnumerationShouldWork() { Fixture.Add(0, "hello"); Fixture.Add(0, "cat"); Fixture.Add(0, "dog"); Fixture.Add(1, "house"); Fixture.Add(2, "pool"); Fixture.Add(2, "office"); Fixture.Select(s => s.Key).Should().Contain(new[] { 0, 1, 2 }); Fixture.SelectMany(s => s).Should().Contain(new[] { "hello", "cat", "dog", "house", "pool", "office" }); } }
我有同样的问题和疑问。 为什么Lookup是不可变的? 我用IDictionary的一些扩展方法解决了它
上述就是C#学习教程:为什么Lookup在C#中是不可变的?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
public static void Add(this IDictionary dict,TKey key,TItem item) where TList : ICollection,new() { if(!dict.ContainsKey(key)) { dict.Add(key, new TList()); } dict[key].Add(item); } public static void Remove(this IDictionary dict, TKey key) where TList : IEnumerable , new() { if (dict.ContainsKey(key)) { dict.Remove(key); } } public static TList Items(this IDictionary dict, TKey key) where TList : IEnumerable , new() { if (dict.ContainsKey(key)) { return dict[key]; } return default(TList); }
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/991435.html