通过IList后门通用列表

时间:2010-11-12 13:02:06

标签: c# generics ilist

我有一个场景,其中一个类加载一种类型的对象,因为抽象我不能使用泛型类(泛型往往像癌症一样传播:)但我经常想要检索一般版本的对象,这导致代码像这样(简化):

List<SomeClass> items = Storage.LoadItems(filename).OfType<SomeClass>().ToList();

在LoadItems返回List&lt; object&gt;的地方,我意识到,为什么不反而

public void LoadItems(string filename,IList list);

现在我可以这样做

List<SomeClass> items = new  List<SomeClass>();
LoadItems(filename,items);

哪个应该更有效率。由于我可以使用现有的List并添加新项目,因此它似乎也更灵活一些。所以我的问题是,这是一种常见模式还是你有不同/更好的方法来实现这一目标?

我也有点好奇你可以这样做,如果你尝试添加一个错误类型的对象你得到一个例外,但这是否意味着通用列表也进行类型检查? (这似乎有点不必要)

修改 将模式修改为

实际上可能更优雅一些
public IList LoadItems(string filename,IList list=null);

这样你可以流利地使用该语句,如果没有传递列表,你可以简单地实例化一个List&lt; object&gt;

4 个答案:

答案 0 :(得分:3)

List<T>明确实施IList。 实现转换为T并调用常规(通用)方法。

因此,只有在显式调用IList方法时才会进行类型检查。 例如:

void System.Collections.IList.Insert(int index, Object item) 
{
    ThrowHelper.IfNullAndNullsAreIllegalThenThrow<T>(item, ExceptionArgument.item); 

    try {
        Insert(index, (T) item); 
    }
    catch (InvalidCastException) {
        ThrowHelper.ThrowWrongValueTypeArgumentException(item, typeof(T));
    } 
}

它不使用as关键字,因为T可能是值类型 如果您撰写as T,则只能撰写where T : class

答案 1 :(得分:1)

在大多数情况下使用IList很好;并且肯定比使用反射或dynamic实现相同的速度更快。

是的,它会添加一个类型检查(凭借cast / unbox),但这不会是繁重的。如果Tstruct,那么你也会有一些拳击/拆箱,但这也不像人们所担心的那么糟糕。

在那种情况下,IList对我没问题。

答案 2 :(得分:0)

您的解决方案看起来确实合理,但没有任何问题。

关于Add,它实际上并没有进行类型检查。您引用的Add的代码是:

int System.Collections.IList.Add(Object item)
{
    try {
        Add((T) item);
    }
    catch (InvalidCastException) {
        throw ...;
    }

    return Count - 1;
}

它不进行类型检查;它只是一个尝试/捕获。

答案 3 :(得分:0)

我喜欢第二种方法。

您可以传递IList但是然后检查类型以查看它是否是通用列表,如果是,则获取泛型类型并仅加载该类型的记录:

   Type itemType = typeof (object);
   if(list.GetType().GetGenericArguments().Length>0)
   {
       itemType = list.GetType().GetGenericArguments()[0];
   }

   for (int i = 0; i < recordCount; i++)
   {
      if(record.GetType().IsInstanceOfType(itemType))
   }