.net 是否有KeyedCollection的一般具体实现?
该类是一个非常有用的替代方法,特别是当关键数据是所存储对象的一部分或者您希望能够按顺序枚举项时。不幸的是,这个类是抽象的,我无法在核心.NET框架中找到一个通用的具体实现 这本书指出应该为抽象类型提供一个具体的实现(第4.4节抽象类设计)。为什么框架设计人员会忽略这样一个有用类的一般具体实现,特别是当它可以通过简单地公开一个构造函数来提供时,该构造函数接受并存储从项到其键的.net 是否有KeyedCollection的一般具体实现?,.net,collections,.net,Collections,该类是一个非常有用的替代方法,特别是当关键数据是所存储对象的一部分或者您希望能够按顺序枚举项时。不幸的是,这个类是抽象的,我无法在核心.NET框架中找到一个通用的具体实现 这本书指出应该为抽象类型提供一个具体的实现(第4.4节抽象类设计)。为什么框架设计人员会忽略这样一个有用类的一般具体实现,特别是当它可以通过简单地公开一个构造函数来提供时,该构造函数接受并存储从项到其键的 public class ConcreteKeyedCollection<TKey, TItem> : Key
public class ConcreteKeyedCollection<TKey, TItem> : KeyedCollection<TKey, TItem>
{
private Converter<TItem, TKey> getKeyForItem = null;
public ConcreteKeyedCollection(Converter<TItem, TKey> getKeyForItem)
{
if (getKeyForItem == null) { throw new ArgumentNullException("getKeyForItem"); }
this.getKeyForItem = getKeyForItem;
}
protected override TKey GetKeyForItem(TItem item)
{
return this.getKeyForItem(item);
}
}
公共类ConcreteKeyedCollection:KeyedCollection
{
私有转换器getKeyForItem=null;
public-KeyedCollection(转换器getKeyForItem)
{
如果(getKeyForItem==null){抛出新的ArgumentNullException(“getKeyForItem”);}
this.getKeyForItem=getKeyForItem;
}
受保护的覆盖TKey GetKeyForItem(TItem项目)
{
返回此.getKeyForItem(项目);
}
}
有具体的实现,包括(但不限于):
- (我经常使用这个类)
根据你问题的精神,没有通用的实现,因为我不为微软工作,所以我只能推测。因为具体的实现就像您所展示的那样简单,所以我不会提供任何推测(因为这可能是错误的)。下面是我提出的实现
public class LookupKeyedCollection<TKey, TItem> : KeyedCollection<TKey, TItem>
{
private Func<TItem, TKey> _getKeyFunc;
public LookupKeyedCollection(Func<TItem, TKey> getKeyFunc)
{
_getKeyFunc = getKeyFunc;
}
//Required KeyedCollection implementation
protected override TKey GetKeyForItem(TItem item)
{
return _getKeyFunc(item);
}
public bool TryGetItem(TKey key, out TItem item)
{
if (Dictionary == null)
{
item = default(TItem);
return false;
}
return Dictionary.TryGetValue(key, out item);
}
public void AddOrUpdate(TItem item)
{
Remove(_getKeyFunc(item));
Add(item);
}
public new bool Contains(TItem item)
{
return base.Contains(_getKeyFunc(item));
}
}
公共类LookupKeyedCollection:KeyedCollection
{
私有函数_getKeyFunc;
公共LookupKeyedCollection(Func getKeyFunc)
{
_getKeyFunc=getKeyFunc;
}
//必需的KeyedCollection实现
受保护的覆盖TKey GetKeyForItem(TItem项目)
{
返回_getKeyFunc(项目);
}
公共布尔测试项目(TKey、out TItem项目)
{
if(Dictionary==null)
{
项目=默认值(滴度);
返回false;
}
返回Dictionary.TryGetValue(key,out项);
}
公共无效地址更新(TItem项目)
{
删除(_getKeyFunc(项目));
增加(项目);
}
公共新bool包含(滴度项目)
{
return base.Contains(_getKeyFunc(item));
}
}
这些方法背后的原因主要有以下几点:
- 我想到了一个。它可以硬编码属性名称,也可以根据需要使用[Key]属性
///// <summary>
///// Creates an indexed list. Requires that [Key] attribute be applied to a property in TValue object.
///// </summary>
///// <example>
///// public class Test
///// {
///// [Key]
///// public int Id { get; set; }
///// }
/////
///// IndexedList<int, Test> tests;
///// </example>
///// <typeparam name="TKey"></typeparam>
///// <typeparam name="TValue"></typeparam>
public class IndexedList<TKey, TValue> : KeyedCollection<TKey, TValue>
{
PropertyInfo keyProperty;
public IndexedList()
{
foreach (var property in typeof(TValue).GetProperties())
{
// this requires .net 4, which I couldn't use due to the WPF shadow effect deprication
//if (property.PropertyType == typeof(TKey) && property.IsDefined(typeof(KeyAttribute), true))
if (property.PropertyType == typeof(TKey) && (property.Name.ToUpper() == "ID" || property.Name.ToUpper() == "KEY"))
{
keyProperty = property;
return;
}
}
throw new ArgumentException(String.Format("Unable to find a property in {0} that is named Id or Key and is of type {1}.", typeof(TValue).Name, typeof(TKey).Name));
}
protected override TKey GetKeyForItem(TValue item)
{
return (TKey)keyProperty.GetValue(item, null);
}
}
//
/////创建索引列表。要求将[Key]属性应用于TValue对象中的属性。
/////
/////
/////公开课考试
///// {
/////[关键]
/////公共int Id{get;set;}
///// }
/////
/////指数试验;
/////
/////
/////
公共类索引列表:KeyedCollection
{
财产信息关键财产;
公共索引列表()
{
foreach(typeof(TValue).GetProperties()中的var属性)
{
//这需要.NET4,由于WPF阴影效果去润滑,我无法使用它
//if(property.PropertyType==typeof(TKey)和&property.IsDefined(typeof(KeyAttribute),true))
if(property.PropertyType==typeof(TKey)&(property.Name.ToUpper()==“ID”| | property.Name.ToUpper()==“KEY”))
{
keyProperty=属性;
返回;
}
}
抛出新ArgumentException(String.Format(“无法在{0}中找到名为Id或Key且类型为{1}的属性”)、typeof(TValue.Name、typeof(TKey.Name));
}
受保护的覆盖TKey GetKeyForItem(TValue项)
{
return(TKey)keyProperty.GetValue(item,null);
}
}
没有具体实现的原因是它不可序列化(不能序列化委托)。BCL中的所有集合都可以序列化
这就是为什么最好继承和重写该方法,尤其是当您无法预测集合将如何使用时。新公共bool Contains(TItem item)方法是什么?请参阅第一个链接(它已断开,因此我切换到wayback机器)最好称之为
TryGetItem
@nawfal我认为关键是要掩盖原始包含的,它可能有错误的语义。@OhadSchneider我的意思是你可以将TryGetValue
重命名为TryGetItem
。后者在KeyedCollection上下文中传达了正确的含义。“IndexedList”听起来有点多余。列表基本上是在.NET中编制索引的。它也没有给出键控索引的概念。“KeyedList”听起来更好。