C#中IList与List区别

本文探讨了IList与List在.NET Framework中的区别,并通过具体示例介绍了如何利用IList实现集合的深拷贝。文章还讨论了在不同场景下选择IList或List的原因。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先IList 泛型接口是 ICollection 泛型接口的子代,并且是所有泛型列表的基接口。

它仅仅是所有泛型类型的接口,并没有太多方法可以方便实用,如果仅仅是作为集合数据的承载体,确实,IList<T>可以胜任。

不过,更多的时候,我们要对集合数据进行处理,从中筛选数据或者排序。这个时候IList<T>就爱莫能助了。

1、当你只想使用接口的方法时,ILis<>这种方式比较好.他不获取实现这个接口的类的其他方法和字段,有效的节省空间.

2、IList <>是个接口,定义了一些操作方法这些方法要你自己去实现
List <>是泛型类,它已经实现了IList <>定义的那些方法

IList <Class1> IList11 =new List <Class1>();
List <Class1> List11 =new List <Class1>();

这两行代码,从操作上来看,实际上都是创建了一个List<Class1>对象的实例,也就是说,他们的操作没有区别。

只是用于保存这个操作的返回值变量类型不一样而已。

那么,我们可以这么理解,这两行代码的目的不一样。
List <Class1> List11 =new List <Class1>();
是想创建一个List<Class1>,而且需要使用到List<T>的功能,进行相关操作。

IList <Class1> IList11 =new List <Class1>();
只是想创建一个基于接口IList<Class1>的对象的实例,只是这个接口是由List<T>实现的。所以它只是希望使用到IList<T>接口规定的功能而已。

应用场景
对一个集合进行深拷贝复制,实现的方法有不少,现举一个常规实现方案:例如已有一个List<T> someList
List<T> newList = new List<T>(); foreach(var item in someList) { T t = new T(); //此处的属性如果是引用类型,还需要考虑该类型的深拷贝实现 t.P1 = item.P1; t.P2 = item.P2; }

如果类似的需求不止一个,那我们就要反复书写类似的代码,这显然不符合代码重用的原则。 思路

首先想到的应该是扩展方法,并且是基于泛型的扩展方法,这个简单,上代码:

public static IList<T> Clone<T>(this IList<T> source) { IList<T> newList = new List<T>(source.Count); foreach (var item in source) { newList.Add(..); } return newList; }

这个add方法里还是要new一个T对象,并且挨个给属性赋值,那岂不是也很麻烦,这时候肯定有同学想到了反射,对,使用反射可以解决这个问题,但我认为还不是很理想。

第二次思考。。。对了,微软不是已经为我们提供了一个接口叫ICloneable的么?我们应该为T加上约束,修改代码如下:

public static IList<T> Clone<T>(this IList<T> source) where T : ICloneable { IList<T> newList = new List<T>(source.Count); foreach (var item in source) { newList.Add((T)((ICloneable)item.Clone())); } return newList; }

现在看上去还不错了,基本思路已经成型,在调用的时候可以这样使用: newList = someList.Clone();

当然,别忘了给你的T加上ICloneable接口,并实现Clone方法,实现Clone的方法有很多,个人建议如下:

public object Clone() { MemoryStream stream = new MemoryStream(); BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(stream, this); stream.Position = 0; var obj = formatter.Deserialize(stream) as Class; return obj; }
使用序列化的方式进行对象的复制,这样做的前提是你的Class需要被标记为Serializable。 使用EF时碰到的实际案例 例如一个Entity有很多关联的实体(主子表),现在需要复制原始记录作为一份全新的记录,包括所有的子表,如果采用常规方法,做起来是会很繁琐的,需要挨个遍历子表集合,并new一个全新的实体对象,再挨个执行AddObject,如果采用上面的方案,代码如下:
//子表集合 var resList = this.ResourcePlanService.GetList(t => t.QuoteID == quoteId).ToList(); ForeachCopy(resList, this.ResourcePlanService); private void ForeachCopy<TModel, TService>(IList<TModel> list, TService service) where TService : IService<TModel> where TModel : ICloneable { list.Clone().ForEach( t => service.Add(t) ); }
这样代码就精简了很多,对原来的改动也相对较小,只需要把TModel的基类EntityObjectBase实现ICloneable接口,并实现Clone方法即可,需要注意的是,如果EF采用DB First方式,则需要在Clone方法里面把EntityKey设置为null,否则,在调用AddObject的时候,ObjectManagement会抛出异常。 总结

优点:代码简单、复用度高

缺点:需要修改类对象以继承ICloneable接口,如果没有基类的话,也是一个很麻烦的问题,并且类对象需要被标记为Serializable



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值