如果我在以下C#场景中已经有正确的类型,有没有办法避免Cast <T>()?

Mar*_*kus 2 c# linq

public class ItemStore {
    private Dictionary<Type, List<object>> _items = new Dictionary<Type, List<object>>();

    public void AddItem(object item) {
        var type = item.GetType();
        if (!_items.ContainsKey(type)) {
            _items[type] = new List<object>();
        }
        _items[type].Add(item);
    }

    public IEnumerable<T> GetItems<T>() {
        if(!_items.ContainsKey(typeof(T))) {
            return new List<T>();
        }
        return _items[typeof(T)].Cast<T>();
    }
}
Run Code Online (Sandbox Code Playgroud)

(真实场景更复杂,它是一个在多个项目中使用的库,对于具体类型一无所知....)

Cast<T>()GetItems()会消耗相当长的一段时间.所以我宁愿避免它.有没有办法在C#中避免它 - 因为实际上列表已经包含了正确的类型?

Mik*_*ray 7

您需要稍微修改此类的内部结构,以便在项目查找中不使用泛型,因为我们需要将存储列表的基础类型作为正确的类型.创建列表时需要稍加反思.我们还可以通过避免额外的查找来使AddItem和GetItems更有效:

public class ItemStore {
    private Dictionary<Type, IList> _items = new Dictionary<Type, IList>();

    public void AddItem(object item) {
        var type = item.GetType();
        IList list;
        if (!_items.TryGetValue(type, out list)) {
            var listType = typeof(List<>).MakeGenericType(type);
            list = (IList)Activator.CreateInstance(listType);
            _items[type] = list;
        }

        list.Add(item);
    }

    public IEnumerable<T> GetItems<T>() {
        IList list;
        if(!_items.TryGetValue(typeof(T), out list)) {
            return Enumerable.Empty<T>();
        } else {
            return (IEnumerable<T>)list;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果你可以修改AddItem的签名,这可能更简单(没有反射),但鉴于你说这是一个过度简化,我将保持公共API不变.