常用接口
用于比较接口
IComparable
接口内部定义了用于比较两个对象大小的CompareTo(T t)方法,>参数时返回1,=参数时返回0,<参数时返回-1。集合类型的Sort方法的排序逻辑正是隐式地调用了此接口的CompareTo方法,Sort方法按CompareTo方法返回的值来确定应如何对元素进行排序,默认情况下是按从小到大进行排序。如果不喜欢使用此接口指定比较逻辑来排序,还可以直接使用Comparison<T>(T t1,T t2)委托,该委托作为Sort方法的参数被自动调用,你可以传递给Sort方法一个匹配Comparison<T>委托签名的lambda表达式用以指定比较的逻辑。
{
public int Score { get; set; }
//比较成绩
public int CompareTo(Student other)
{
return Score > other.Score ? 1 : Score < other.Score ? -1 : 0;
}
}
public class Programe
{
static void Main(string[] args)
{
Student stu1 = new Student { Score = 100 };
Student stu2 = new Student { Score = 90 };
int result=stu1.CompareTo(stu2);
Console.WriteLine(result); //print 1
}
}
IComparer
接口内部定义了用于比较两个对象大小的Compare(T x, T y)方法,x>y时返回1,x=y时返回0,x
{
//比较成绩
public int Compare(Student x, Student y)
{
return x.Score > y.Score ? 1 : x.Score < y.Score ? -1 : 0;
}
}
public class Student
{
public int Score { get; set; }
}
public class Programe
{
static void Main(string[] args)
{
Student stu1 = new Student { Score = 100 };
Student stu2 = new Student { Score = 90 };
int result = new CompareObject().Compare(stu1, stu2);
Console.WriteLine(result); //print 1
}
}
用于测试相等性的比较接口
IEquatable
接口内部定义了用于测试相等性的Equals(T other)方法。当前对象和参数对象相等则返回true,否则返回false。
{
public long Id { get; set; }
public string Name { get; set; }
public bool Equals(Employee other)
{
return other == null ? false : other.Name == Name ? true : false;
}
}
public class Programe
{
static void Main(string[] args)
{
var em = new Employee { Id = 1, Name = "sam" };
var em2 = new Employee { Id = 1, Name = "sam" };
Console.WriteLine(em.Equals(em2)); //print true
}
}
IEqualityComparer
接口内部定义了用于测试相等性的Equals(T x , T y)方法和GetHashCode(T obj)方法。x和y相等则返回true,否则返回false。
如果想要两个版本的Equals()方法,比如一个用于测试两个对象的地址引用的相等性,另一个用于测试两个对象的属性的等同性,可考虑保持继承的Object的Equals()方法和GetHashCode()方法不变,然后通过实现IEqualityComparer
{
public class Employee
{
public long Id { get; set; }
public string Name { get; set; }
}
public class EmployeesEqualName : IEqualityComparer<Employee>
{
public bool Equals(Employee x, Employee y)
{
return object.ReferenceEquals(x, y) ? true : x == null || y == null ? false : x.Name == y.Name ? true : false;
}
public int GetHashCode(Employee obj)
{
return obj.Name.GetHashCode();
}
}
public class Programe
{
static void Main(string[] args)
{
var em = new Employee { Id = 1, Name = "sam" };
var em2 = new Employee { Id = 1, Name = "sam" };
Console.WriteLine(new EmployeesEqualName().Equals(em, em2)); //print true
Dictionary<Employee, string> dictionarys = new Dictionary<Employee, string>(new EmployeesEqualName())
{
{ em,"1" },
{ em2,"2"}
};
Console.WriteLine(dictionarys.ContainsKey(em2));//抛出异常 因为属性值相等,em2不会作为key被添加
}
}
}
用于类型转换的接口
IConvertible
接口内部定义了17个方法用于类型的强制转换,可实现自定义的转换规则。
用于泛型集合的接口
IEnumerable
接口内部只有一个方法,这个方法叫做GetEnumerator(),该方法返回一个IEnumerator
IEnumerator
接口内部定义了获取泛型集合中的当前元素、将指针移动到下一个元素、将指针归位的方法,所有实现了IEnumerable接口的泛型集合类型都通过实现其GetEnumerator()方法,该方法返回一个实现了迭代集合枚举数:IEnumerator实例,因为枚举的复杂度,C#已隐藏枚举的具体实现,建议通过foreach语句迭代集合元素。 最后注意,任何正在进行迭代的集合,都不要试图在这个过程中为集合执行添加、删除、修改操作,这些行为将被视为无效,如果修改值,编译器会提示错误,添加、删除不会提示错误,但这些行为是无效的。因为这样做会引起歧义,正在迭代当中却试图为集合执行增删改,那么枚举数就不知道接下来应该将改动视为一次迭代还是应忽视它们。
Current
//当前枚举中的元素
MoveNext()
//将枚举器的指针移动到下一个元素
Reset()
//将枚举器的指针归位,在索引0之前
内置的集合类型都可以使用for、foreach、集合.GetEnumerator()方法这三种方式迭代集合,但如果你要想让自定义的泛型集合也可以被迭代,你就必须手动实现IEnumerable
利用集合接口实现自定义泛型集合
自定义集合的初始化器
自定义一个公开的Add(Object obj)方法用于使集合初始化器可以正确添加项。下面是一个简陋的例子,只为说明如何为自定义集合添加初始化器:
{
public string Name { get; set; }
}
public class TestCollection : IEnumerable
{
public void Add(Animal a)
{
throw new NotImplementedException();
}
public IEnumerator GetEnumerator()
{
throw new NotImplementedException();
}
}
TestCollection myLlist = new TestCollection
{
new Animal{ Name="sam" },
new Animal{ Name="korn" }
};
实现的步骤
1.定义支持集合初始化器的方法,一个Add(T obj)方法
2.实现IEnumerable
3.定义支持通过索引获取项的索引器,有了索引器就可以使用for语句迭代每个项
4.创建一个可迭代的枚举器,必须实现IEnumerator
{
public class Programe
{
public class Animal
{
public string Name { get; set; }
}
public class Aggregates<T> : IEnumerable<T>, IEnumerable
{
private List<T> Elms = new List<T>();
//集合的初始化器
public void Add(T t)
{
Elms.Add(t);
}
//索引器
public T this[int index]
{
get
{
return Elms.Any() ? index > (Elms.Count - 1) ? default(T) : Elms[index] : default(T);
}
set
{
if (Elms.Any())
{
if (index <= (Elms.Count - 1))
{
Elms[index] = value;
}
}
}
}
public IEnumerator<T> GetEnumerator()
{
return new AggregatesEnumerator<T>(Elms);
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public class AggregatesEnumerator<T> : IEnumerator<T>
{
public List<T> list;
private int indexer;
public T Current => list[indexer];
object IEnumerator.Current => list[indexer];
public AggregatesEnumerator(List<T> xAggregates)
{
list = xAggregates;
indexer = -1;
}
public void Dispose() { }
public bool MoveNext()
{
indexer++;
return indexer != list.Count();
}
public void Reset()
{
indexer = -1;//游标归位
}
}
static void Main(string[] args)
{
Aggregates<Animal> list = new Aggregates<Animal>
{
new Animal{ Name="sam" },
new Animal{ Name="korn" },
new Animal{ Name="landy" }
};
//IEnumerator迭代
var ItemRator = list.GetEnumerator();
while (ItemRator.MoveNext())
{
Console.WriteLine(ItemRator.Current.Name);
}
//foreach迭代
foreach (var item in list)
{
Console.WriteLine(item.Name);
}
//for迭代
for (int i = 0; i < list.Count(); i++)
{
Console.WriteLine(list[i].Name);
}
}
}
}
以上实现起始内部依然是通过将项存储在一个List
{
return Elms.GetEnumerator ( );
}
IEnumerator IEnumerable.GetEnumerator ( )
{
return GetEnumerator ( );
}
yield关键字
{
yield return "leo"; //"运行时"会自动保存当前迭代的状态,下一次迭代时将根据被保存的迭代状态直接从上一次的位置向下移动一个项
yield return "sam";
yield return "korn";
yield return "landy";
}
{
for ( int i = 0 ; i < Elms.Count ; i++ )
{
yield return Elms [ i ];
}
}
//或:
public IEnumerator
{
for ( int i = 0 ; i < Elms.Count ; i++ )
{
if ( Elms [ i ] == null )
{
yield break; //取消当前迭代
}
yield return Elms [ i ];
}
}
yield return仅支持在返回IEnumerator
public IEnumerable
{
for ( int i = Elms.Count - 1 ; i >= 0 ; i-- )
{
yield return Elms [ i ];
}
}
foreach ( var item in 你的自定义的集合.GetReverseEnumerator ( ) )
{
Console.WriteLine ( item.Name );
}
IQueryable
提供针对特定数据源评估查询的功能。IQueryable
ICollection
Count
//获取项的总量
Add(T t)
//将参数添加到集合
Clear()
//从字典中移除所有的键和值
Contains(T t)
//确定集合是否包含参数指定的项
GetEnumerator()
//获取枚举数
Remove(T t)
//从集合中移除参数所指定的项
CopyTo(T[] TArray, int index)
//拷贝数组到参数指定的数组,可指定从哪个索引作为拷贝的起始位置。如果是引用类型则会发生一次浅拷贝,两个数组会指向同一个引用
实现了ICollection接口的泛型集合
Queue<T>;
Stack<T>;
Dictionary<TKey, TValue>;
SortedList<TKey, TValue>;
IDictionary
接口内部定义了泛型字典集合的属性与方法
Count
//获取项的总量
Keys
//获取键的集合
Values
//获取值的集合
Add(TKey, TValue)
//将指定的键和值添加到字典中
Clear()
//从字典中移除所有的键和值
ContainsKey(TKey)
//确定字典是否包含指定的键
ContainsValue(TValue)
//确定字典是否包含指定的值
Equals(object x)
//确定相等性
GetEnumerator()
//获取枚举数
GetHashCode()
//获取哈希值
GetObjectData(SerializationInfo info, StreamingContext context)
//实现System.Runtime.Serialization.ISerializable接口,并返回序列化Dictionary
Remove(TKey)
//从字典中移除键所指定的记录
IList
接口内部定义了泛型列表集合的属性与方法
Count
//获取列表的项个数
Contains(T item)
//列表是否包含参数指定的元素
FindAll(Predicate<in T> match)
//根据泛型委托执行搜索
//示例:
var records = list.FindAll((employee) => (employee.Id | 1) != employee.Id); //Id是偶数的记录
BinarySearch(T item)
//使用二进制搜索查找元素,查不到返回-1,此方法与线性查找的效率相比,数据量大应采用BinarySearch,否则采用线性查找
CopyTo(T[] TArray, index)
//拷贝数组到参数指定的数组,可指定从哪个索引作为拷贝的起始位置。如果是引用类型则会发生一次浅拷贝,两个数组会指向同一个引用
Add(T item)
//向列表添加元素,数组没有实现这个方法,因为数组的长度是恒定的
Remove(T item)
//移除列表中由参数指定的元素,数组没有实现这个方法
RemoveAt(int index)
//移除列表中由参数指定的索引处的元素,数组没有实现这个方法
Insert(int index, T item)
//在参数指定的索引处插入一个新的元素,数组没有实现这个方法
Clear()
//清空列表,数组没有实现这个方法
泛型集合(Generic)
Dictionary 哈希字典集合类
此类实现了IDictionary
SortedList 可排序哈希字典集合类
此类实现了IDictionary
List 列表集合类
此类实现了IList
List<int> intList= list.ConvertAll(item => int.Parse(item)); //接收一个 Converter
Stack 栈集合类
此类实现了ICollection接口,它表示一个后进先出的栈集合,虽然元素有其索引,但因为元素压入之后只能从顶部取出,所以并不支持索引访问元素、也不支持初始化器。栈元素的插入称为入栈,元素的删除称为出栈。默认容量(capacity)是10,可通过重载的构造函数指定这个参数,也可以通过添加元素使容量自动增长。
stack.Push(new Person { Name = "sam" });
stack.Push(new Person { Name = "leo" });
stack.Push(new Person { Name = "korn" });
Console.WriteLine(stack.Count);
int[] intArray = { 1, 2, 3 };
Stack stack2 = new Stack(intArray);
Console.Write(stack.Peek()); // print 3
Queue 单项队列集合类
此类实现了ICollection接口,表示一个先进先出的队列集合,虽然元素有其索引,但因为元素压入之后只能从右边出口取出,所以并不支持索引访问元素、也不支持初始化器。队列元素的插入称为入队,元素的删除称为出队。默认容量(capacity)是32,增量系数是2.0(growthFactor),如果容量达到32则其容量会x2倍增。可通过重载的构造函数指定这两个参数,也可以通过添加元素使容量自动增长。类似的有Queue
C# - 学习总目录