首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >带空集合的ILookup

带空集合的ILookup
EN

Stack Overflow用户
提问于 2018-02-06 07:20:24
回答 1查看 873关注 0票数 1

是否有什么内在的错误

代码语言:javascript
复制
IDictionary<int, IEnumerable<string>>

使用

代码语言:javascript
复制
ILookup<int, string>

我更喜欢ILookup而不是IDictionary,因为它更“诚实”的界面和不变性。

但是,我发现ILookup无法保存空集合,因此包含空集合的键根本不存在。这是个问题,因为我还希望ILookup能够传递关于所有可能的键的信息(尽管其中一些键可能是空的),所以我可以这样做:

代码语言:javascript
复制
var statistics = from grouping in myLookup
                 select new {grouping.Key, grouping.Count()};

它适用于可枚举的字典,但不幸的是,它不适用于ILookup。不可能有grouping.Count()==0的条目,就像IDictionary一样。正如约翰·斯基特所说,

在查找和字典之间还有一个重要的区别:如果您请求查找对应于它不知道的键的序列,它将返回一个空序列,而不是抛出一个异常。(查找所知道的密钥永远不会产生空序列。)

现在,如果ILookup允许空分组,又有什么问题呢?为了在这两个方面都发挥最好的作用,我将为ILookup添加Filter()扩展方法,该方法就是这样做的,但需要解决Linq不允许创建空IGroupings的问题(因此我必须实现自己的类),但我觉得可能是在违背Linq的设计原则。

示例

EN

回答 1

Stack Overflow用户

发布于 2018-02-06 09:08:27

有两种选择:

1)您可以创建一个简单明了的EmptyLookup类,如下所示:

代码语言:javascript
复制
var empty = EmptyLookup<int, string>.Instance;

// ...

public static class EmptyLookup<TKey, TElement>
{
    private static readonly ILookup<TKey, TElement> _instance
        = Enumerable.Empty<TElement>().ToLookup(x => default(TKey));

    public static ILookup<TKey, TElement> Instance
    {
        get { return _instance; }
    }
}

2)可以为空查找创建一个单例类。

代码语言:javascript
复制
public sealed class EmptyLookup<T, K> : ILookup<T, K> 
{
        private static readonly EmptyLookup<T, K> _instance 
            = new EmptyLookup<T, K>();

        public static EmptyLookup<T, K> Instance
        {
            get { return _instance; }
        }

        private EmptyLookup() { }

        public bool Contains(T key)
        {
            return false;
        }

        public int Count
        {
            get { return 0; }
        }

        public IEnumerable<K> this[T key]
        {
            get { return Enumerable.Empty<K>(); }
        }

        public IEnumerator<IGrouping<T, K>> GetEnumerator()
        {
            yield break;
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            yield break;
        }
    }
then you can write code like this:

var x = EmptyLookup<int, int>.Instance;
/*The benefit of creating a new class is that you can use the "is" operator and check for type equality:*/

if (x is EmptyLookup<,>) {
 // ....
}

保持空分组是查找是没有错的,只是查找不支持它,因为它在Linq中是自然的。

您必须自己创建一个扩展方法。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48637498

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档