【ZT】利用反射排序泛型List
2011-01-06 11:29
225 查看
http://xianqiang.blog.163.com/blog/static/45268171200981110488644/
ints.Add(1);
ints.Add(10);
ints.Add(42);
List<object> objects = new List<object>();
方法一:
参考地址:http://msdn.microsoft.com/zh-cn/library/ms228359(VS.80).aspx
public static void Add<S, D>(List<S> source, List<D> destination) where S : D
{
foreach (S sourceElement in source)
{
destination.Add(sourceElement);
}
}
VarianceWorkaround.Add<int, object>(ints, objects);
方法二:参考MSDN的List<T>成员函数ConvertAll<TOutput>
先看下泛型委托
public delegate void Del<T>(T item);
public static void Notify(int i) { }
Del<int> m1 = new Del<int>(Notify);
C# 2.0 版具有称为方法组转换的新功能,此功能适用于具体委托类型和泛型委托类型,并使您可以使用如下简化的语法写入上一行:
Del<int> m2 = Notify;
说了泛型委托后,言归正传,先定义一个类型转换方法
public static object intToObj(int item)
{//负责把 int 转换成 object 的函数
return (object) item ;
}
就可以直接用ConvertAll<TOutput>方法了
list<object> obj = ints.ConvertAll( new Converter<int,object> (intToObj) )
这样就ok了,完成List<T>的类型转换了
其中 ConvertAll<TOutput>方法是将当前 List<T> 中的元素转换为另一种类型,并返回包含转换后的元素的列表。 方法定义如下:
public List<TOutput> ConvertAll<TOutput>( Converter<T, TOutput> converter)
下面是这个ConvertAll<TOutput>方法用到的委托
public delegate TOutput Converter<TInput, TOutput>( TInput input)
泛型的总结
泛型最常见的用途是泛型集合,命名空间System.Collections.Generic 中包含了一些基于泛型的集合类,使用泛型集合类可以提供更高的类型安全性,还有更高的性能,避免了非泛型集合的重复的装箱和拆箱。
很多非泛型集合类都有对应的泛型集合类,下面是常用的非泛型集合类以及对应的泛型集合类:
非泛型集合类 泛型集合类
ArrayList List<T>
HashTable DIctionary<T>
Queue Queue<T>
Stack Stack<T>
SortedList SortedList<T>
我们用的比较多的非泛型集合类主要有 ArrayList类 和 HashTable类。我们经常用HashTable 来存储将要写入到数据库或者返回的信息,在这之间要不断的进行类型的转化,增加了系统装箱和拆箱的负担,如果我们操纵的数据类型相对确定的化 用 Dictionary<TKey,TValue> 集合类来存储数据就方便多了,例如我们需要在电子商务网站中存储用户的购物车信息( 商品名,对应的商品个数)时,完全可以用 Dictionary<string, int> 来存储购物车信息,而不需要任何的类型转化。
List类
注意:此类在 .NET Framework 2.0 版中是新增的。表示可通过索引访问的对象的强类型列表。提供用于对列表进行搜索、排序和操作的方法。命名空间: System.Collections.Generic,程序集:mscorlib(在 mscorlib.dll 中),List 类是 ArrayList 类的泛型等效类。
//声明一个泛型类
class TestGenericList
...{
static void Main()
...{
//声明一个List对象,只加入string参数
List<string> names = new List<string>();
names.Add("乔峰");
names.Add("欧阳峰");
names.Add("马蜂");
//遍历List
foreach (string name in names)
...{
Console.WriteLine(name);
}
//向List中插入元素
names.Insert(2, "张三峰");
//移除指定元素
names.Remove("马蜂");
}
}
在决定使用 List 还是使用 ArrayList 类(两者具有类似的功能)时,记住 List 类在大多数情况下执行得更好并且是类型安全的。如果对 List 类的类型 T 使用引用类型,则两个类的行为是完全相同的。但是,如果对类型 T 使用值类型,则需要考虑实现和装箱问题。
如果对类型 T 使用值类型,则编译器将特别针对该值类型生成 List 类的实现。这意味着不必对 List 对象的列表元素进行装箱就可以使用该元素,并且在创建大约 500 个列表元素之后,不对列表元素装箱所节省的内存将大于生成该类实现所使用的内存。
其实我们也可以自己定义一个泛型类,如下所示:
//声明一个泛型类
public class ItemList<T>
...{
void Add(T item) ...{ }
}
class TestGenericList
...{
private class ExampleClass ...{ }
static void Main()
...{
// 声明一个对象,只能加入int型
ItemList<int> list1 = new ItemList<int>();
//声明一个对象,只能加入Student类型,Student类为自定义类
ItemList<Student> list2 = new ItemList<Student>();
}
}
泛型的用法还有很多种,如泛型方法,泛型委托,泛型接口等。
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>接口规定的功能而已。
C#里List的用法
主程序代码:
Code
static void Main(string[] args)
{
ClassList listClass = new ClassList();
Console.WriteLine("请输入第个字符串");
string a = Console.ReadLine();
Console.WriteLine("请输入第二个字符串");
string b = Console.ReadLine();
foreach (string n in listClass.strList(a, b))
{
Console.WriteLine(n);
}
类:
class ClassList
{
public List<string> strList(string str1,string str2)
{
string stra = str1 + str2;
string strb = str2 + str1;
string strc = str1 + str1;
List<string> listStr = new List<string>();
listStr.Add(stra);
listStr.Add(strb);
listStr.Add(strc);
return listStr;
}
}
Code
public class Person
{
private string _name;
private string _like;
public string Name
{
get
{
return this._name;
}
set
{
this._name = value;
}
}
public string Like
{
get
{
return this._like;
}
set
{
this._like = value;
}
}
}
IList<Person> myPerson = new List<Person>();
Person person = new Person();
person.Like = "pingpong";
person.Name = "panjun";
myPerson.Add(person);
foreach (Person person1 in myPerson)
{
this.label1.Text += person1.Name + person1.Like;
}
Dictionary
此类在 .NET Framework 2.0 版中是新增的。表示键和值的集合。命名空间:System.Collections.Generic,程序集:mscorlib(在 mscorlib.dll 中)
class TestGenericList
...{
static void Main()
...{
//声明对象,参数表示,键是int类型,值是string类型
Dictionary<int, string> fruit = new Dictionary<int, string>();
try...{
//加入重复键会引发异常
fruit.Add(1, "苹果");
fruit.Add(2, "桔子");
fruit.Add(3, "香蕉");
fruit.Add(4, "菠萝");
//参数错误将引发异常,如下所示
//fruit.Add("5", "aa");
}
catch (ArgumentException)
...{
Console.WriteLine("添加错误!!!");
}
//因为引入了泛型,所以键取出后不需要进行Object到int的转换,值的集合也一样
foreach (int i in fruit.Keys)
...{
Console.WriteLine("键是:{0} 值是:{1}",i,fruit);
}
//删除指定键,值
fruit.Remove(1);
//判断是否包含指定键
if (fruit.ContainsKey(1))
...{
Console.WriteLine("包含此键");
}
//清除集合中所有对象
fruit.Clear();
}
}
Dictionary遍历输出的顺序,就是加入的顺序,这点与Hashtable不同,其它方法如:ContainsKey ,ContainsValue ,Remove 等,使用方法基本一致。
======================================================================================
.NET(C#) Hashtable Dictionary 探索
先看下面的代码
using System;
using System.Collections;
namespace NoSortHashtable
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class Class1
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main(string[] args)
{
Hashtable hashTable = new Hashtable();
hashTable.Add("hunan","changsha");
hashTable.Add("beijing","beijing");
hashTable.Add("anhui","hefei");
hashTable.Add("sichuan","chengdu");
foreach(string str in hashTable.Keys)
{
Console.WriteLine(str + " : " + hashTable);
}
}
}
}
打印的结果是:
anhui : hefei
hunan : changsha
sichuan : chengdu
beijing : beijing
为何产生这样的结果? 我查了MSDN后发现 ----------------------------------------------------------------------------------------------------Hashtable 对象由包含集合元素的存储桶组成。存储桶是 Hashtable 中各元素的虚拟子组,与大多数集合中进行的搜索和检索相比,存储桶可令搜索和检索更为便捷。每一存储桶都与一个哈希代码关联,该哈希代码是使用哈希函数生 成的并基于该元素的键。
哈希函数是基于键返回数值哈希代码的算法。键是正被存储的对象的某一属性的值。哈希函数必须始终为相同的键返回相同的哈希代码。一个哈希函数能够为两个不同的键生成相同的哈希代码,但从哈希表检索元素时,为每一唯一键生成唯一哈希代码的哈希函数将令性能更佳。
在 Hashtable 中用作元素的每一对象必须能够使用 GetHashCode 方法的实现为其自身生成哈希代码。但是,还可以通过使用接受 IHashCodeProvider 实现作为参数之一的 Hashtable 构造函数,为 Hashtable 中的所有元素指定一个哈希函数。
在将一个对象添加到 Hashtable 时,它被存储在存储桶中,该存储桶与匹配该对象的哈希代码的哈希代码关联。在 Hashtable 内搜索一个值时,将为该值生成哈希代码,并且搜索与该哈希代码关联的存储桶。
例如,一个字符串的哈希函数可以采用该字符串中每一字符的 ASCII 代码并它们添加到一起来生成一个哈希代码。字符串“picnic”将具有与字符串“basket”的哈希代码不同的哈希代码;因此,字符串 “picnic”和“basket”将处于不同的存储桶中。与之相比,“stressed”和“desserts”将具有相同的哈希代码并将处于相同的存 储桶中。
Dictionary 类与 Hashtable 类的功能相同。对于值类型,特定类型(不包括 Object)的 Dictionary 的性能优于 Hashtable,这是因为 Hashtable 的元素属于 Object 类型,所以在存储或检索值类型时通常发生装箱和取消装箱操作。
----------------------------------------------------------------------------------------------------
产生这个结果的原因就是Hashtable内部的排序机制使然,但我现在就是不想排序,我按什么顺序输入的,就想它再怎么给我输出,怎么办?google 后发现几个可以解决的办法,不过都需要自己写代码实现比如,继承hashtable,使用不自动排序的arraylist做中间桥
using System;
using System.Collections;
namespace NoSortHashtable
{
public class NoSortHashtable : Hashtable
{
private ArrayList keys = new ArrayList();
public NoSortHashtable()
{
}
public override void Add(object key, object value)
{
base.Add (key, value);
keys.Add (key);
}
public override ICollection Keys
{
get
{
return keys;
}
}
public override void Clear()
{
base.Clear ();
keys.Clear ();
}
public override void Remove(object key)
{
base.Remove (key);
keys.Remove (key);
}
public override IDictionaryEnumerator GetEnumerator()
{
return base.GetEnumerator ();
}
}
}
或者只要Compare函数的返回结果不等于0就可以添加相同的Key,这样可以实现既可以排序,又可以有相同的Key值,可能在某些情况下会用得到。 using System;
using System.Collections;
namespace testSortedList
{
class Class1
{
static void Main(string[] args)
{
SortedList sl = new SortedList(new MySort()); //不排序
sl.Add(333,333);
sl.Add(111,111);
sl.Add(222,222);
sl.Add(111,112);
PrintList(sl);
Console.ReadLine();
}
private static void PrintList(SortedList sl)
{
for(int i=0;i<sl.Count ;i++)
{
Console.WriteLine("{0}\t{1}",sl.GetKey(i),sl.GetByIndex(i));
}//end for
}//end fn()
}
public class MySort:IComparer
{
#region IComparer 成员
public int Compare(object x, object y)
{
return -1;
//排序
// int iResult = (int)x - (int)y;
// if(iResult == 0) iResult = -1;
// return iResult;
}
#endregion
}
}
使用单链接列表实现 IDictionary。建议用于通常包含 10 个或 10 个以下项的集合。
最后我测试了使用泛类型的Dictionary<T,T>, 尽管msdn上说hashtable和Dictionary的实现是一样的,不过同样的数据,返回的结果却是不同的,我没有找到更多的解释,测试代码如下
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Collections.Generic;
namespace NoSortHashtable
{
/// <summary>
/// Summary description for Class1.
/// </summary>
public class Class1
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main(string[] args)
{
Hashtable ht = new Hashtable();
ht.Add("hunan","changsha");
ht.Add("beijing","beijing");
ht.Add("anhui","hefei");
ht.Add("sichuan","chengdu");
foreach(string str in ht.Keys)
{
Console.WriteLine(str + " : " + ht);
}
Console.WriteLine("------------------------------------");
Dictionary<String,String> dic = new Dictionary<String,String>();
dic.Add("hunan","changsha");
dic.Add("beijing","beijing");
dic.Add("anhui","hefei");
dic.Add("sichuan","chengdu");
foreach(string str in dic.Keys)
{
Console.WriteLine(str + " : " + dic);
}
Console.WriteLine("------------------------------------");
ListDictionary lsdic = new ListDictionary();
lsdic.Add("hunan","changsha");
lsdic.Add("beijing","beijing");
lsdic.Add("anhui","hefei");
lsdic.Add("sichuan","chengdu");
foreach(string str in lsdic.Keys)
{
Console.WriteLine(str + " : " + lsdic);
}
}
}
}
另外,System.Collections.Specialized.ListDictionary也是可以完成该要求的,不过。。。
========================================================================================
3個對泛型 List 排序的方法
方式1:
List<SoftDrink> list = manager.SoftDrink.ListSoftDrink();
list.Sort(new MyComp().Compare);
list.Sort(new MyCompDesc().Compare);
public class MyComp : IComparer<SoftDrink> {
public int Compare(SoftDrink x, SoftDrink y) {
return String.Compare(x.SerialId, y.SerialId);
}
}
public class MyCompDesc : IComparer<SoftDrink> {
public int Compare(SoftDrink x, SoftDrink y) {
return String.Compare(y.SerialId, x.SerialId);
}
}
方式2:
list.Sort(
new Comparison<SoftDrink>(
delegate(SoftDrink x, SoftDrink y) {
return String.Compare(x.SerialId, y.SerialId);
}));
list.Sort(
new Comparison<SoftDrink>(
delegate(SoftDrink x, SoftDrink y) {
return String.Compare(y.SerialId, x.SerialId);
}));
方式3: 使用 Dynamic Reflection Library
DynamicComparer<SoftDrink> comparer = new DynamicComparer<SoftDrink>("SerialId");
DynamicComparer<SoftDrink> comparerDesc = new DynamicComparer<SoftDrink>("SerialId DESC");
list.Sort(comparer);
list.Sort(comparerDesc);
在List有90筆 SoftDrink的情況下,對List正排倒排連續做1000次
方法1: 0.424 秒
方法2: 0.393 秒
方法3: 1.859 秒
方法3: 0.527 秒 (如果new Comparer()放在迴圈外)
不要覺得 Dynamic Reflection Library 慢就沒用呀,他能容易的對多屬性做排序,而速度差異也不大
比較糟的是,如果我的物件裏有子物件,我要對依子物件的屬性做排序,他就辦不到了。
http://blog.csdn.net/cxb_wind/archive/2008/04/10/2277670.aspx
In the follow example, I created a simple class:
public class Person
{
private int _id;
private string _name;
public int ID { get{ return _id;} set{ _id = value;}}
public int Name { get{ return _name;} set{ _name= value;}}
public Person(int id, string name)
{
_id = id;
_name = name;
}
}
In the example, there's a simple class with two private attributes. Now we're going to create a typed List of this object and take advantage of the Find() method
public void CreateAndSearchList()
{
//create and fill the collection
List<Person> myList = new List<Person>();
myList.Add(new Person(1, "AndreySanches"));
myList.Add(new Person(2, "AlexandreTarifa"));
myList.Add(new Person(3, "EmersonFacunte"));
//find a specific object
Person myLocatedObject = myList.Find(delegate(Person p) {return p.ID == 1; });
}
备注:在list和array集合中搜索元素经常使用该方法,主要技术是泛型委托
list用法注意:如果增加一个对象,必须重新new一个对象,看下面的例子:
person p=new pewson();
for(int i=0;i<5;i++)
{
p.ID=i;
p.Name="xxxx";
list.add(p);
}
for(int i=0;i<5;i++)
{
person p=new person();
p.ID=i;
p.Name="xxxx";
list.add(p);
}
上面有区别吗?在输出list的值是有区别了,第一个list里面存放的都是一样的,结果和最后一个一样,都是同一个人对象,第二个list达到预 期的效果,存储不同的人对象。这是为什么?原因很简单,一个list对象中存储的都是对一个共有的对象进行引用,所以以最后改变的值为准。
对象的排序:本文主要阐述对存储datatable的list进行按TableName排序
1、新建一个sort类
public class SceneSort:IComparer<DataTable>
{
public int Compare(DataTable obj1, DataTable obj2)
{
int tableNameLength1;
int tableNameLength2;
if (obj1 == null)
{
if (obj2 == null)
return 0;
else
return -1;
}
else
{
if (obj2 == null)
return 1;
else
{
tableNameLength1=obj1.TableName.Length;
tableNameLength2=obj2.TableName.Length;
if (Convert.ToInt32(obj1.TableName.Substring(2,tableNameLength1-2))>Convert.ToInt32(obj2.TableName.Substring(2,tableNameLength2-2)))
return 1; //大于返回1
else if (Convert.ToInt32(obj1.TableName.Substring(2,tableNameLength1-2))<Convert.ToInt32(obj2.TableName.Substring(2,tableNameLength2-2)))
return -1; //小于返回-1
else
return 0; //相等返回0
}
}
}
2 排序:
List<DataTable> ldt = new List<DataTable>();
SceneSort ss=new SceneSort ();
tablelist.sort(ss);即可对list进行排序;
/article/5494807.html
思路已经有了,但动手写代码前,google了一下相关文章,竟然发现有一段功能类似的代码,唯一不同是该该代码的实现中方法并不是泛型的。但是强大的地方是,代码中对实现的排序支持按照多个属性排序。于是稍加修改,一段强大的支持按照多属性对List进行排序的泛型方法就出炉了。
首先是表示排序属性和排序方向的类SortClass,其中保存了排序的属性和排序的方向。
代码private List<T> TableToList<T>(T obj, DataTable tt)
{
System.Type type = obj.GetType();
List<T> list = new List<T>();
for (int i = 0; i < tt.Rows.Count; i++)
{
T item = (T)Activator.CreateInstance(type);
object value;
foreach (DataColumn c in tt.Columns)
{
value = tt.Rows[i][c];
if (value != System.DBNull.Value)
{
type.GetProperty(c.ColumnName).SetValue(item, tt.Rows[i][c], null);
}
}
list.Add(item);
}
return list;
}1. System.Type type = obj.GetType(); 获取类型信息,例如,你想把DataTable最后转换为List<Product>,那么这里的T 的Type就是Product.
2. List<T> list = new List<T>(); 定义你要返回的列表,如上面提到的
List<Product>,因为DataTable的每一行的数据就可以填充一个对象,DataTable所有的数据当然就得返回为List了。
3 . T item = (T)Activator.CreateInstance(type); 根据之前获取的类型信息创建一个实例,你在程序中用的肯定就是对象的实例。
4..
object value;
foreach (DataColumn c in tt.Columns)
{
value = tt.Rows[i][c];
if (value != System.DBNull.Value)
{
type.GetProperty(c.ColumnName).SetValue(item, tt.Rows[i][c], null);
}
}
看到 type.GetProperty(c.ColumnName).SetValue(item, tt.Rows[i][c], null);分解如下:
type.GetProperty(c.ColumnName)(通过属性的名字) 获取之前创建的那个实例的属性的信息,注意:你的实体类的的属性名必须和数据库中表的列名一样。
SetValue(item, tt.Rows[i][c], null); 给属性赋值
OK
泛型集合List<T>类型转换
List<int> ints = new List<int>();ints.Add(1);
ints.Add(10);
ints.Add(42);
List<object> objects = new List<object>();
方法一:
参考地址:http://msdn.microsoft.com/zh-cn/library/ms228359(VS.80).aspx
public static void Add<S, D>(List<S> source, List<D> destination) where S : D
{
foreach (S sourceElement in source)
{
destination.Add(sourceElement);
}
}
VarianceWorkaround.Add<int, object>(ints, objects);
方法二:参考MSDN的List<T>成员函数ConvertAll<TOutput>
先看下泛型委托
public delegate void Del<T>(T item);
public static void Notify(int i) { }
Del<int> m1 = new Del<int>(Notify);
C# 2.0 版具有称为方法组转换的新功能,此功能适用于具体委托类型和泛型委托类型,并使您可以使用如下简化的语法写入上一行:
Del<int> m2 = Notify;
说了泛型委托后,言归正传,先定义一个类型转换方法
public static object intToObj(int item)
{//负责把 int 转换成 object 的函数
return (object) item ;
}
就可以直接用ConvertAll<TOutput>方法了
list<object> obj = ints.ConvertAll( new Converter<int,object> (intToObj) )
这样就ok了,完成List<T>的类型转换了
其中 ConvertAll<TOutput>方法是将当前 List<T> 中的元素转换为另一种类型,并返回包含转换后的元素的列表。 方法定义如下:
public List<TOutput> ConvertAll<TOutput>( Converter<T, TOutput> converter)
下面是这个ConvertAll<TOutput>方法用到的委托
public delegate TOutput Converter<TInput, TOutput>( TInput input)
泛型的总结
泛型最常见的用途是泛型集合,命名空间System.Collections.Generic 中包含了一些基于泛型的集合类,使用泛型集合类可以提供更高的类型安全性,还有更高的性能,避免了非泛型集合的重复的装箱和拆箱。
很多非泛型集合类都有对应的泛型集合类,下面是常用的非泛型集合类以及对应的泛型集合类:
非泛型集合类 泛型集合类
ArrayList List<T>
HashTable DIctionary<T>
Queue Queue<T>
Stack Stack<T>
SortedList SortedList<T>
我们用的比较多的非泛型集合类主要有 ArrayList类 和 HashTable类。我们经常用HashTable 来存储将要写入到数据库或者返回的信息,在这之间要不断的进行类型的转化,增加了系统装箱和拆箱的负担,如果我们操纵的数据类型相对确定的化 用 Dictionary<TKey,TValue> 集合类来存储数据就方便多了,例如我们需要在电子商务网站中存储用户的购物车信息( 商品名,对应的商品个数)时,完全可以用 Dictionary<string, int> 来存储购物车信息,而不需要任何的类型转化。
List类
注意:此类在 .NET Framework 2.0 版中是新增的。表示可通过索引访问的对象的强类型列表。提供用于对列表进行搜索、排序和操作的方法。命名空间: System.Collections.Generic,程序集:mscorlib(在 mscorlib.dll 中),List 类是 ArrayList 类的泛型等效类。
//声明一个泛型类
class TestGenericList
...{
static void Main()
...{
//声明一个List对象,只加入string参数
List<string> names = new List<string>();
names.Add("乔峰");
names.Add("欧阳峰");
names.Add("马蜂");
//遍历List
foreach (string name in names)
...{
Console.WriteLine(name);
}
//向List中插入元素
names.Insert(2, "张三峰");
//移除指定元素
names.Remove("马蜂");
}
}
在决定使用 List 还是使用 ArrayList 类(两者具有类似的功能)时,记住 List 类在大多数情况下执行得更好并且是类型安全的。如果对 List 类的类型 T 使用引用类型,则两个类的行为是完全相同的。但是,如果对类型 T 使用值类型,则需要考虑实现和装箱问题。
如果对类型 T 使用值类型,则编译器将特别针对该值类型生成 List 类的实现。这意味着不必对 List 对象的列表元素进行装箱就可以使用该元素,并且在创建大约 500 个列表元素之后,不对列表元素装箱所节省的内存将大于生成该类实现所使用的内存。
其实我们也可以自己定义一个泛型类,如下所示:
//声明一个泛型类
public class ItemList<T>
...{
void Add(T item) ...{ }
}
class TestGenericList
...{
private class ExampleClass ...{ }
static void Main()
...{
// 声明一个对象,只能加入int型
ItemList<int> list1 = new ItemList<int>();
//声明一个对象,只能加入Student类型,Student类为自定义类
ItemList<Student> list2 = new ItemList<Student>();
}
}
泛型的用法还有很多种,如泛型方法,泛型委托,泛型接口等。
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>接口规定的功能而已。
C#里List的用法
主程序代码:
Code
static void Main(string[] args)
{
ClassList listClass = new ClassList();
Console.WriteLine("请输入第个字符串");
string a = Console.ReadLine();
Console.WriteLine("请输入第二个字符串");
string b = Console.ReadLine();
foreach (string n in listClass.strList(a, b))
{
Console.WriteLine(n);
}
类:
class ClassList
{
public List<string> strList(string str1,string str2)
{
string stra = str1 + str2;
string strb = str2 + str1;
string strc = str1 + str1;
List<string> listStr = new List<string>();
listStr.Add(stra);
listStr.Add(strb);
listStr.Add(strc);
return listStr;
}
}
Code
public class Person
{
private string _name;
private string _like;
public string Name
{
get
{
return this._name;
}
set
{
this._name = value;
}
}
public string Like
{
get
{
return this._like;
}
set
{
this._like = value;
}
}
}
IList<Person> myPerson = new List<Person>();
Person person = new Person();
person.Like = "pingpong";
person.Name = "panjun";
myPerson.Add(person);
foreach (Person person1 in myPerson)
{
this.label1.Text += person1.Name + person1.Like;
}
Dictionary
此类在 .NET Framework 2.0 版中是新增的。表示键和值的集合。命名空间:System.Collections.Generic,程序集:mscorlib(在 mscorlib.dll 中)
class TestGenericList
...{
static void Main()
...{
//声明对象,参数表示,键是int类型,值是string类型
Dictionary<int, string> fruit = new Dictionary<int, string>();
try...{
//加入重复键会引发异常
fruit.Add(1, "苹果");
fruit.Add(2, "桔子");
fruit.Add(3, "香蕉");
fruit.Add(4, "菠萝");
//参数错误将引发异常,如下所示
//fruit.Add("5", "aa");
}
catch (ArgumentException)
...{
Console.WriteLine("添加错误!!!");
}
//因为引入了泛型,所以键取出后不需要进行Object到int的转换,值的集合也一样
foreach (int i in fruit.Keys)
...{
Console.WriteLine("键是:{0} 值是:{1}",i,fruit);
}
//删除指定键,值
fruit.Remove(1);
//判断是否包含指定键
if (fruit.ContainsKey(1))
...{
Console.WriteLine("包含此键");
}
//清除集合中所有对象
fruit.Clear();
}
}
Dictionary遍历输出的顺序,就是加入的顺序,这点与Hashtable不同,其它方法如:ContainsKey ,ContainsValue ,Remove 等,使用方法基本一致。
======================================================================================
.NET(C#) Hashtable Dictionary 探索
先看下面的代码
using System;
using System.Collections;
namespace NoSortHashtable
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class Class1
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main(string[] args)
{
Hashtable hashTable = new Hashtable();
hashTable.Add("hunan","changsha");
hashTable.Add("beijing","beijing");
hashTable.Add("anhui","hefei");
hashTable.Add("sichuan","chengdu");
foreach(string str in hashTable.Keys)
{
Console.WriteLine(str + " : " + hashTable);
}
}
}
}
打印的结果是:
anhui : hefei
hunan : changsha
sichuan : chengdu
beijing : beijing
为何产生这样的结果? 我查了MSDN后发现 ----------------------------------------------------------------------------------------------------Hashtable 对象由包含集合元素的存储桶组成。存储桶是 Hashtable 中各元素的虚拟子组,与大多数集合中进行的搜索和检索相比,存储桶可令搜索和检索更为便捷。每一存储桶都与一个哈希代码关联,该哈希代码是使用哈希函数生 成的并基于该元素的键。
哈希函数是基于键返回数值哈希代码的算法。键是正被存储的对象的某一属性的值。哈希函数必须始终为相同的键返回相同的哈希代码。一个哈希函数能够为两个不同的键生成相同的哈希代码,但从哈希表检索元素时,为每一唯一键生成唯一哈希代码的哈希函数将令性能更佳。
在 Hashtable 中用作元素的每一对象必须能够使用 GetHashCode 方法的实现为其自身生成哈希代码。但是,还可以通过使用接受 IHashCodeProvider 实现作为参数之一的 Hashtable 构造函数,为 Hashtable 中的所有元素指定一个哈希函数。
在将一个对象添加到 Hashtable 时,它被存储在存储桶中,该存储桶与匹配该对象的哈希代码的哈希代码关联。在 Hashtable 内搜索一个值时,将为该值生成哈希代码,并且搜索与该哈希代码关联的存储桶。
例如,一个字符串的哈希函数可以采用该字符串中每一字符的 ASCII 代码并它们添加到一起来生成一个哈希代码。字符串“picnic”将具有与字符串“basket”的哈希代码不同的哈希代码;因此,字符串 “picnic”和“basket”将处于不同的存储桶中。与之相比,“stressed”和“desserts”将具有相同的哈希代码并将处于相同的存 储桶中。
Dictionary 类与 Hashtable 类的功能相同。对于值类型,特定类型(不包括 Object)的 Dictionary 的性能优于 Hashtable,这是因为 Hashtable 的元素属于 Object 类型,所以在存储或检索值类型时通常发生装箱和取消装箱操作。
----------------------------------------------------------------------------------------------------
产生这个结果的原因就是Hashtable内部的排序机制使然,但我现在就是不想排序,我按什么顺序输入的,就想它再怎么给我输出,怎么办?google 后发现几个可以解决的办法,不过都需要自己写代码实现比如,继承hashtable,使用不自动排序的arraylist做中间桥
using System;
using System.Collections;
namespace NoSortHashtable
{
public class NoSortHashtable : Hashtable
{
private ArrayList keys = new ArrayList();
public NoSortHashtable()
{
}
public override void Add(object key, object value)
{
base.Add (key, value);
keys.Add (key);
}
public override ICollection Keys
{
get
{
return keys;
}
}
public override void Clear()
{
base.Clear ();
keys.Clear ();
}
public override void Remove(object key)
{
base.Remove (key);
keys.Remove (key);
}
public override IDictionaryEnumerator GetEnumerator()
{
return base.GetEnumerator ();
}
}
}
或者只要Compare函数的返回结果不等于0就可以添加相同的Key,这样可以实现既可以排序,又可以有相同的Key值,可能在某些情况下会用得到。 using System;
using System.Collections;
namespace testSortedList
{
class Class1
{
static void Main(string[] args)
{
SortedList sl = new SortedList(new MySort()); //不排序
sl.Add(333,333);
sl.Add(111,111);
sl.Add(222,222);
sl.Add(111,112);
PrintList(sl);
Console.ReadLine();
}
private static void PrintList(SortedList sl)
{
for(int i=0;i<sl.Count ;i++)
{
Console.WriteLine("{0}\t{1}",sl.GetKey(i),sl.GetByIndex(i));
}//end for
}//end fn()
}
public class MySort:IComparer
{
#region IComparer 成员
public int Compare(object x, object y)
{
return -1;
//排序
// int iResult = (int)x - (int)y;
// if(iResult == 0) iResult = -1;
// return iResult;
}
#endregion
}
}
使用单链接列表实现 IDictionary。建议用于通常包含 10 个或 10 个以下项的集合。
最后我测试了使用泛类型的Dictionary<T,T>, 尽管msdn上说hashtable和Dictionary的实现是一样的,不过同样的数据,返回的结果却是不同的,我没有找到更多的解释,测试代码如下
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Collections.Generic;
namespace NoSortHashtable
{
/// <summary>
/// Summary description for Class1.
/// </summary>
public class Class1
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main(string[] args)
{
Hashtable ht = new Hashtable();
ht.Add("hunan","changsha");
ht.Add("beijing","beijing");
ht.Add("anhui","hefei");
ht.Add("sichuan","chengdu");
foreach(string str in ht.Keys)
{
Console.WriteLine(str + " : " + ht);
}
Console.WriteLine("------------------------------------");
Dictionary<String,String> dic = new Dictionary<String,String>();
dic.Add("hunan","changsha");
dic.Add("beijing","beijing");
dic.Add("anhui","hefei");
dic.Add("sichuan","chengdu");
foreach(string str in dic.Keys)
{
Console.WriteLine(str + " : " + dic);
}
Console.WriteLine("------------------------------------");
ListDictionary lsdic = new ListDictionary();
lsdic.Add("hunan","changsha");
lsdic.Add("beijing","beijing");
lsdic.Add("anhui","hefei");
lsdic.Add("sichuan","chengdu");
foreach(string str in lsdic.Keys)
{
Console.WriteLine(str + " : " + lsdic);
}
}
}
}
另外,System.Collections.Specialized.ListDictionary也是可以完成该要求的,不过。。。
========================================================================================
3個對泛型 List 排序的方法
方式1:
List<SoftDrink> list = manager.SoftDrink.ListSoftDrink();
list.Sort(new MyComp().Compare);
list.Sort(new MyCompDesc().Compare);
public class MyComp : IComparer<SoftDrink> {
public int Compare(SoftDrink x, SoftDrink y) {
return String.Compare(x.SerialId, y.SerialId);
}
}
public class MyCompDesc : IComparer<SoftDrink> {
public int Compare(SoftDrink x, SoftDrink y) {
return String.Compare(y.SerialId, x.SerialId);
}
}
方式2:
list.Sort(
new Comparison<SoftDrink>(
delegate(SoftDrink x, SoftDrink y) {
return String.Compare(x.SerialId, y.SerialId);
}));
list.Sort(
new Comparison<SoftDrink>(
delegate(SoftDrink x, SoftDrink y) {
return String.Compare(y.SerialId, x.SerialId);
}));
方式3: 使用 Dynamic Reflection Library
DynamicComparer<SoftDrink> comparer = new DynamicComparer<SoftDrink>("SerialId");
DynamicComparer<SoftDrink> comparerDesc = new DynamicComparer<SoftDrink>("SerialId DESC");
list.Sort(comparer);
list.Sort(comparerDesc);
在List有90筆 SoftDrink的情況下,對List正排倒排連續做1000次
方法1: 0.424 秒
方法2: 0.393 秒
方法3: 1.859 秒
方法3: 0.527 秒 (如果new Comparer()放在迴圈外)
不要覺得 Dynamic Reflection Library 慢就沒用呀,他能容易的對多屬性做排序,而速度差異也不大
比較糟的是,如果我的物件裏有子物件,我要對依子物件的屬性做排序,他就辦不到了。
http://blog.csdn.net/cxb_wind/archive/2008/04/10/2277670.aspx
C#中List用法
How to find objects in Generics with List.Find() method
I've been looking for help on how to find objects in Generics with List.Find() method .... and ... take a look what I have found.In the follow example, I created a simple class:
public class Person
{
private int _id;
private string _name;
public int ID { get{ return _id;} set{ _id = value;}}
public int Name { get{ return _name;} set{ _name= value;}}
public Person(int id, string name)
{
_id = id;
_name = name;
}
}
In the example, there's a simple class with two private attributes. Now we're going to create a typed List of this object and take advantage of the Find() method
public void CreateAndSearchList()
{
//create and fill the collection
List<Person> myList = new List<Person>();
myList.Add(new Person(1, "AndreySanches"));
myList.Add(new Person(2, "AlexandreTarifa"));
myList.Add(new Person(3, "EmersonFacunte"));
//find a specific object
Person myLocatedObject = myList.Find(delegate(Person p) {return p.ID == 1; });
}
备注:在list和array集合中搜索元素经常使用该方法,主要技术是泛型委托
list用法注意:如果增加一个对象,必须重新new一个对象,看下面的例子:
person p=new pewson();
for(int i=0;i<5;i++)
{
p.ID=i;
p.Name="xxxx";
list.add(p);
}
for(int i=0;i<5;i++)
{
person p=new person();
p.ID=i;
p.Name="xxxx";
list.add(p);
}
上面有区别吗?在输出list的值是有区别了,第一个list里面存放的都是一样的,结果和最后一个一样,都是同一个人对象,第二个list达到预 期的效果,存储不同的人对象。这是为什么?原因很简单,一个list对象中存储的都是对一个共有的对象进行引用,所以以最后改变的值为准。
对象的排序:本文主要阐述对存储datatable的list进行按TableName排序
1、新建一个sort类
public class SceneSort:IComparer<DataTable>
{
public int Compare(DataTable obj1, DataTable obj2)
{
int tableNameLength1;
int tableNameLength2;
if (obj1 == null)
{
if (obj2 == null)
return 0;
else
return -1;
}
else
{
if (obj2 == null)
return 1;
else
{
tableNameLength1=obj1.TableName.Length;
tableNameLength2=obj2.TableName.Length;
if (Convert.ToInt32(obj1.TableName.Substring(2,tableNameLength1-2))>Convert.ToInt32(obj2.TableName.Substring(2,tableNameLength2-2)))
return 1; //大于返回1
else if (Convert.ToInt32(obj1.TableName.Substring(2,tableNameLength1-2))<Convert.ToInt32(obj2.TableName.Substring(2,tableNameLength2-2)))
return -1; //小于返回-1
else
return 0; //相等返回0
}
}
}
2 排序:
List<DataTable> ldt = new List<DataTable>();
SceneSort ss=new SceneSort ();
tablelist.sort(ss);即可对list进行排序;
/article/5494807.html
利用反射排序泛型List
在最近一个项目中,有需求要对页面中所有的gridview添加排序功能。由于gridview的数据源绑定的是一个集合类List,而不是DataTable,所以无法使用DataView排序功能。另外,不同的gridview显示的是不同的业务数据,为了重用代码只能添加一个泛型方法,使用该方法对数据类型T,按照任意给定的属性进行排序。由于是要按照某个不固定的属性对List内的对象进行排序,所以修改类型T,使之实现IComparable接口,并利用List类的Sort () 方法进行排序是无法满足需求的。但是List类还提供了另一个Sort方法,它接受一个IComparer对象作为参数,在IComparer内可以实现排序的业务逻辑。唯一需要的就是进行排序的属性了,而这个在程序的上下文是已知的。思路已经有了,但动手写代码前,google了一下相关文章,竟然发现有一段功能类似的代码,唯一不同是该该代码的实现中方法并不是泛型的。但是强大的地方是,代码中对实现的排序支持按照多个属性排序。于是稍加修改,一段强大的支持按照多属性对List进行排序的泛型方法就出炉了。
首先是表示排序属性和排序方向的类SortClass,其中保存了排序的属性和排序的方向。
代码private List<T> TableToList<T>(T obj, DataTable tt)
{
System.Type type = obj.GetType();
List<T> list = new List<T>();
for (int i = 0; i < tt.Rows.Count; i++)
{
T item = (T)Activator.CreateInstance(type);
object value;
foreach (DataColumn c in tt.Columns)
{
value = tt.Rows[i][c];
if (value != System.DBNull.Value)
{
type.GetProperty(c.ColumnName).SetValue(item, tt.Rows[i][c], null);
}
}
list.Add(item);
}
return list;
}1. System.Type type = obj.GetType(); 获取类型信息,例如,你想把DataTable最后转换为List<Product>,那么这里的T 的Type就是Product.
2. List<T> list = new List<T>(); 定义你要返回的列表,如上面提到的
List<Product>,因为DataTable的每一行的数据就可以填充一个对象,DataTable所有的数据当然就得返回为List了。
3 . T item = (T)Activator.CreateInstance(type); 根据之前获取的类型信息创建一个实例,你在程序中用的肯定就是对象的实例。
4..
object value;
foreach (DataColumn c in tt.Columns)
{
value = tt.Rows[i][c];
if (value != System.DBNull.Value)
{
type.GetProperty(c.ColumnName).SetValue(item, tt.Rows[i][c], null);
}
}
看到 type.GetProperty(c.ColumnName).SetValue(item, tt.Rows[i][c], null);分解如下:
type.GetProperty(c.ColumnName)(通过属性的名字) 获取之前创建的那个实例的属性的信息,注意:你的实体类的的属性名必须和数据库中表的列名一样。
SetValue(item, tt.Rows[i][c], null); 给属性赋值
OK
相关文章推荐
- 利用反射排序泛型List
- 三层架构之数据访问层,利用反射返回IList泛型集合
- 利用反射 和 comparator 实现List 的简单排序
- DataTable转任意类型对象List数组-----工具通用类(利用反射和泛型)
- 利用反射实现mysql数据库sql查询 返回List<E>泛型(持久化)对象
- C# 利用list.sort()进行排序
- C#中利用LINQ to XML与反射把任意类型的泛型集合转换成XML格式字符串的方法
- 泛型加反射,DataSet转换为List
- 利用Java反射机制将Json格式字符串反射为 Bean List
- 利用反射,泛型,静态方法快速获取表单值到Model。
- 绕过泛型,通过反射把 String 添加到 List<Integer> 中
- 黑马程序员--Java基础加强--17.利用反射操作泛型VI【泛型类型变量的语义】【GenericDeclaration接口】【泛型接口TypeVariable】【通过Class反射解析泛型类】
- DataGridView绑定泛型List时,利用BindingList来实现增删查改
- 利用反射和泛型让JDBC编程方便点
- 利用反射,泛型获取/存储表单值到Model
- LinkedList中将对象按照某一属性排序,利用 collection.sort(); 来进行调用!
- 利用List统计文件中单词个数,并排序输出
- List<>泛型排序,快速去重复
- winform中利用反射实现泛型数据访问对象基类(2)
- 利用反射,泛型,静态方法快速获取表单值到Model。(Henq)