通过 IList 对通用列表进行后门处理
我有一个场景,一个类加载一种类型的对象,由于抽象,我不能使用泛型类(泛型往往像癌症一样传播:),但我经常想在检索到对象后使用泛型版本,这导致在这样的代码中(简化):
List<SomeClass> items = Storage.LoadItems(filename).OfType<SomeClass>().ToList();
其中 LoadItems 返回一个 List
public void LoadItems(string filename,IList list);
现在我可以这样做,
List<SomeClass> items = new List<SomeClass>();
LoadItems(filename,items);
这应该更有效。它似乎也更灵活一些,因为我可以采用现有列表并添加新项目。所以我的问题是,这是一种常见模式还是您有不同/更好的方法来实现这一目标?
我也有点好奇你可以这样做,如果你尝试添加错误类型的对象,你会得到一个异常,但这是否意味着通用列表也会进行类型检查? (这似乎有点不必要)
编辑 实际上,修改模式可能会更优雅一些,这样
public IList LoadItems(string filename,IList list=null);
您就可以流畅地使用语句,并且如果没有传递列表,您可以简单地实例化一个 List
I have a scenario where a class loads objects of one type, due do abstractions I can not use a generic class (generics tend to spread like cancer :) but I often want to work with a generic version of the objects once retrieved, which resulted in code like this (simplified):
List<SomeClass> items = Storage.LoadItems(filename).OfType<SomeClass>().ToList();
Where LoadItems returns a List<object>, then I realized, why not instead have
public void LoadItems(string filename,IList list);
Now I can do this instead
List<SomeClass> items = new List<SomeClass>();
LoadItems(filename,items);
Which should be more efficient. It's also seems a bit more flexible since I can take an existing List and tack on new items. So my questions are, is this a common pattern or do you have a different/better way of achieving this?
I'm also a bit curious that you can do this, if you try and add a object of the wrong type you get an exception, but does that mean that generic lists also do a type check? (which seems a bit unecessary)
EDIT
It might actually be a bit more elegant to modify the pattern to
public IList LoadItems(string filename,IList list=null);
that way you can use the statement fluently and if no list is passed you could simply instantiate a List<object>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
List
显式实现IList
。实现强制转换为
T
并调用常规(通用)方法。因此,只有在显式调用
IList
方法时才会进行类型检查。例如:
它不使用
as
关键字,因为T
可能是值类型。如果您写的是
where T : class
,则只能写成as T
。List<T>
implementsIList
explicitly.The implementations cast to
T
and call the regular (generic) methods.Thus, type-checking only happens if you explicitly call the
IList
methods.For example:
It doesn't use the
as
keyword because theT
might be a value type.You can only write
as T
if you wrotewhere T : class
.在大多数情况下,使用
IList
就可以了;并且当然比使用反射或动态
来实现相同的效果更快。是的,它会添加类型检查(通过强制转换/拆箱),但这不会很麻烦。如果
T
是一个struct
那么你也会有一些装箱/拆箱,但这也没有人们担心的那么糟糕。在这种情况下,
IList
对我来说就很好。Using
IList
is fine in most cases; and is certainly faster than using reflection ordynamic
to achieve the same.Yes it will add a type-check (by virtue of the cast/unbox), but that will not be onerous. If
T
is astruct
then you also have some boxing/unboxing, but that too isn't as bad as people fear.In that scenario,
IList
would be fine by me.您的解决方案看起来确实不错,没有任何问题。
关于
Add
,它并没有真正进行类型检查。您引用的Add
的代码是这样的:它不进行类型检查;这只是一个尝试/捕获。
Your solution does look sound, there is nothing wrong with it.
Concerning the
Add
, it doesn't really do a type check. The code for theAdd
you refer to is this:It doesn't do a type check; it's just a try/catch.
我喜欢第二种方法。
您可以传递 IList,但然后检查类型以查看它是否是通用列表,如果是,则获取通用类型并仅加载该类型的记录:
I like the second approach.
You can pass the IList but then check the type to see if it is a generic list and if so, get generic type and load only records of that type: