gpt4 book ai didi

c# - 如何转换查找的 TElement;在。 Lookup 到 ILookup

转载 作者:行者123 更新时间:2023-11-30 15:15:49 27 4
gpt4 key购买 nike

我有一个 ILookup<int, Derived>我想返回 ILookup<int, Base>其中 Derived实现或扩展 Base .

目前我使用SelectMany()然后 ToLookup()首先提取ILookup<int, Derived>的键值对进公寓IEnumerable然后创建一个新的 ILookup<int, Base> :

class Base { }

class Derived: Base { }

class Test
{
ILookup<int, Base> CastLookup(ILookup<int, Derived> existing)
{
IEnumerable<KeyValuePair<int, Base>> flattened = existing.SelectMany(
(x) => x,
(gr, v) => new KeyValuePair<int, Base>(gr.Key, (Base)v)); // I know the explicit cast can be implicit here; it is just to demonstrate where the up casting is happening.
ILookup<int, Base> result = flattened.ToLookup(
(x) => x.Key,
(x) => x.Value);
return result;
}
}

如何在不迭代其条目然后重新打包它们的情况下转换 ILookup?


注意:一个相关的问题是 Shouldn't ILookup<TKey, TElement> be (declared) covariant in TElement?通过 bigge . Ryszard Dżegan answers这主要是出于历史原因:ILookup<TKey, TElement>在具有协变性的泛型之前已经被开发出来。
Herzmeistersomething similar对于 Dictionary<TKey, TValue> . Mehrdad Afshari answers对于可变字典,协方差是不安全的。
事实上,如果 Ilookup<TKey, TElement>TElement 中是协变的, 我不会遇到 ILookup<TKey, TElement> 的这个实例选角问题;但事实并非如此,所以我仍在继续寻求更好的方法。

注意:我当然可以编写扩展方法来执行此操作,但这并不能阻止所需的迭代和重新打包计算工作。

最佳答案

你可以创建一个代理:

public static ILookup<TKey, TValueBase> ToLookupBase<TKey, TValue, TValueBase>(this ILookup<TKey, TValue> lookup)
where TValue : class, TValueBase
{
return new LookupProxy<TKey, TValue, TValueBase>(lookup);
}

public class LookupProxy<TKey, TValue, TValueBase> : ILookup<TKey, TValueBase>
where TValue : class, TValueBase
{
private readonly ILookup<TKey, TValue> lookup;

public LookupProxy(ILookup<TKey, TValue> lookup)
{
this.lookup = lookup;
}

public IEnumerable<TValueBase> this[TKey key] => lookup[key];

public int Count => lookup.Count;

public bool Contains(TKey key) => lookup.Contains(key);

public IEnumerator<IGrouping<TKey, TValueBase>> GetEnumerator() => lookup.GetEnumerator();

IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}

请注意,您必须:

var base = existing.ToLookupBase<int, Derived, Base>();

如此显式地告诉所有泛型参数。如果你甚至想支持 TKey 的协方差,那就有点复杂了,需要一个单独的支持类和一个单独的方法:

public static ILookup<TKeyBase, TValueBase> ToLookupBase2<TKey, TValue, TKeyBase, TValueBase>(ILookup<TKey, TValue> lookup)
where TKey : class, TKeyBase
where TValue : class, TValueBase
{
return new LookupProxy2<TKey, TValue, TKeyBase, TValueBase>(lookup);
}

public class LookupProxy2<TKey, TValue, TKeyBase, TValueBase> : ILookup<TKeyBase, TValueBase>
where TKey : class, TKeyBase
where TValue : class, TValueBase
{
private readonly ILookup<TKey, TValue> lookup;

public LookupProxy2(ILookup<TKey, TValue> lookup)
{
this.lookup = lookup;
}

public IEnumerable<TValueBase> this[TKeyBase key] => key is TKey ? lookup[(TKey)key] : Enumerable.Empty<TValueBase>();

public int Count => lookup.Count;

public bool Contains(TKeyBase key) => key is TKey ? lookup.Contains((TKey)key) : false;

public IEnumerator<IGrouping<TKeyBase, TValueBase>> GetEnumerator() => lookup.GetEnumerator();

IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}

这是因为您需要添加一个 where TKey : class, TKeyBase(它不支持键的值类型,就像您的示例中那样)。

关于c# - 如何转换查找的 TElement;在。 Lookup<TKey, Derived> 到 ILookup<TKey, Base>?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51397920/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com