8

我有一个场景,一个类加载一种类型的对象,由于抽象我不能使用泛型类(泛型往往像癌症一样传播:)但我经常想使用检索到的对象的泛型版本,结果在这样的代码中(简化):

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

LoadItems 返回一个 List<object> 的地方,然后我意识到,为什么不改为

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<object>

4

4 回答 4

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 Twhere T : class

于 2010-11-12T13:04:23.220 回答
1

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

是的,它会添加一个类型检查(通过强制转换/取消框),但这不会很麻烦。如果T是,struct那么您也有一些装箱/拆箱,但这也没有人们担心的那么糟糕。

在那种情况下,IList我会很好。

于 2010-11-12T13:08:26.473 回答
0

您的解决方案看起来确实不错,没有任何问题。

关于Add,它并没有真正进行类型检查。Add您所指的代码是这样的:

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

    return Count - 1;
}

它不做类型检查;这只是一个尝试/捕捉。

于 2010-11-12T13:08:23.540 回答
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))
   }
于 2010-11-12T13:15:12.043 回答