using System;
using System.Collections.Generic; //泛型集合
using System.Linq;
namespace _1_泛型概述
{
class Program
{
static void Main(string[] args)
{
//集合与数组①集合长度可以改变②集合添加数据时,不用考虑数据类型(集合中添加数据自动转换为object类型)③在使用具体元素是需要将元素转换为想要的数据类型
List<int> list = new List<int>(); //尖括号中代表类型(T是类型的总称呼 Type,)整型类型的泛型
list.Add(8);
list.Add(7);
list.AddRange(new int[] { 1, 2, 3, 4, 5, 6 }); //向泛型集合中添加数组
list.AddRange(list); //将自己当做元素添加
list.Reverse(); //倒序
list.Sort(); //排序
list.Insert(3, 100); //在索引值为3的地方插入100;
for (int i = 0; i < list.Count; i++)
Console.WriteLine(list[i]);
int[] nums = list.ToArray(); //将泛型转换为数组
List<int> List2 = nums.ToList(); //将数组转换为泛型集合
Console.ReadKey();
}
}
}
在System.Collections.Generic的命名空间中定义了许多泛型接口和集合类
- List<T>: 用法类似于System.Collections下的ArrayList类,可以动态增大后减小容量,他实现了IList<T> ICollection<T>接口。这个类还支持掐功能;例如:排序,倒序;删除,增加元素等。
- Dictionary<TKey,TValue>:键值对集合类,是在存储键值对的集合类,实现了IDictionary<TKey,TValue> ICollection<KeyValuePair<Tkey,TValue>> ISerializable IDeserialzationCallBack接口
- SortedList<Tkey,TValue>:实现了IDictionary<TKey,TValue> ICollection<KeyValuePir<TKey,TValue>>接口,类似于Dictionary<TKey,TValue>,此集合类可以按照键来排序
- LinkedList<T>:此集合是双向链表,实现了ICollection<T> IEnumerable<T> ISerializble IDeserializationCallBack接口
- Queue<T>:先进先出,在此集合类中先添加的元素会被先读取出,这类似我们打印队列实现的接口有ICollection<T>和IEnumerable<T>接口,还有方法:
- ①Enque在队列的尾部添加对应的对象
- ②Deque:返回队列开头的对象并删除该对象。
- ③Peek:可以在队列中读取第一个对象,但不删除该对象
- Stack<T> :堆栈特性先进后出组合,他实现了ICollection<T> IEnumerable<T> 还有方法
- Push:可以把一个对象添加到堆栈的尾部
- Pop:读取堆栈尾部的对象,并将其删除
- Peek:读取堆栈尾部的对象,但不删除
using System;
namespace 自定义泛型类的创建
{
public class TGeneric<T> //泛型类一般以T开头,类似接口一般用I开头
{
//可以在泛型类中定义字段、属性、方法等
public T Field; //泛型字段
}
class commonlyClass
{
public T G<T>(T t) // 普通方法, G(T t) ,没有自己的类型参数里列表
{
return t;
}
}
class TGeneric2<T>
{
public T M(T t) //泛型方法, 有自己的类型参数列表
{
return t;
}
}
class Program
{
static void Main(string[] args)
{
TGeneric<string> g = new TGeneric<string>();
g.Field = "darly";
Console.WriteLine(g.Field);
Console.WriteLine(g.Field.GetType());
Console.ReadKey();
}
}
}
using System;
namespace _4_类型参数T
{
//定义泛型类
public class TGenericdemon<T>
{
public void Exp(T input)
{
Console.WriteLine(input);
}
}
class Program
{
private class customClass //自定义类别
{
}
static void Main(string[] args)
{
//实例化泛型类 gd1,char
TGenericdemon<char> gd1 = new TGenericdemon<char>();
gd1.Exp('男');
Console.WriteLine("实例化类型为char的TGenericdemon的gd1成功");
//实例化泛型类 gd2,int
TGenericdemon<int> gd2 = new TGenericdemon<int>();
gd2.Exp(2);
Console.WriteLine("实例化类型为int的TGenericdemon的gd2成功");
//实例化泛型类 gd3,string
TGenericdemon<string> gd3 = new TGenericdemon<string>();
gd3.Exp("darly");
Console.WriteLine("实例化类型为String的TGenericdemon的gd3成功");
//实例化泛型了 gd4 自定义的类型
TGenericdemon<customClass> gd4 = new TGenericdemon<customClass>();
//gd4.Exp("darly");
Console.WriteLine("实例化类型为自定义类型的TGenericdemon的gd4成功");
Console.ReadKey();
}
}
}
泛型类是抽象类而非具体的数据类型,那么它是否符合普通的继承规则?答案是肯定的。不同的是在泛型类继承上上,基类和派生类可能只有一个泛型类,也可能二者都是,这样就会出现三种情况
基类 | 派生类 |
---|---|
普通类 | 泛型类 |
泛型类 | 普通类 |
泛型类 | 泛型类 |
using System;
namespace _6_普通类继承泛型类
{
//泛型类继承普通类,并不是普通类继承泛型类
public abstract class baseClass //创建一个普通类作为基类(父类)
{
protected int user_name; //定义字段
public virtual int user_Name //定义属性
{
set { user_name = value; }
get { return user_name; }
}
public baseClass(int index) //构造函数 构造函数没有返回值,连void也不能写,必须public;构造函数的名称必须跟类名一样
{
user_name = index;
}
public abstract void method(int t); //抽象方法 抽象方法不允许任何实现体,包括不允许有{}
}
public class GenClass<T> : baseClass //泛型类继承普通类。起到将类型参数传递给泛型的方式,代表是泛型类
{
protected new T user_name; //隐藏基类中的同名成员(隐藏字段);相当于重新定义(new关键字)了基类中的user_name字段类型,从而达到隐藏基类中字段的作用。
public new T user_Name //隐藏属性
{
get { return user_name; }
}
public GenClass(int index) : base(index) //构造函数可以有多个,此处为构造函数1
{ }
public GenClass(T t) : base(1000) //构造函数可以有多个,此处为构造函数2 ,此处为什么直接写1000,参考下面链接
{
user_name = t;
}
public override void method(int t) //重写普通基类中的抽象方法
{
Console.WriteLine("调用方法成功");
}
public void method(T t)
{ }
}
class Program
{
static void Main(string[] args)
{
int val = 1000;
GenClass<int> g = new GenClass<int>(val);
g.method(g.user_Name);
Console.WriteLine("泛型继承成功:泛型类继承普通类");
Console.ReadKey();
}
}
}
C#中同一个类的多个构造方法之间的调用
由于基类和培生累都是封闭类型,基类和派生类的类型可直接确定。(含有类型参数T的为开放类型,以开放类型为元素的数组类型,开放类型的构造类型都是开放类型(见本文5.1),初次以外都是封闭类型)
using System;
namespace 普通类继承泛型类
{
//定义一个泛型的基类
abstract class genClass<T>
{
protected T field; //定义一个泛型字段
public virtual T Field //定义一个泛型属性
{
get { return field; }
}
public genClass(int index) { } //构造方法
public genClass(T t) { field = t; } //构造方法
public abstract void method(T t);
}
//定义一个普通类,并继承泛型类
class ordinaryClass:genClass<int>
{
public override int Field // 属性重载
{
get
{
return base.Field;
}
}
public ordinaryClass(int t) : base(t) { } //构造函数,构造函数中t需要从基类中获取,类似于继承
public override void method(int t) //重写基类中的抽象方法
{
Console.WriteLine("field属性值为:{0}",t);
}
}
class Program
{
static void Main(string[] args)
{
int val = 1000;
ordinaryClass oc = new ordinaryClass(val);
oc.method(val);
Console.WriteLine("普通类继承泛型类成功");
Console.ReadKey();
}
}
}
这是最为负责的一种,在泛型类与泛型类之间的继承应当注意如下:
using System;
using System.Collections.Generic; //泛型类的命名空间
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _8_泛型类继承泛型类
{
//定义泛型基类,多个参数
// T可以是任意的标识符,只要遵循我们的通常C#命名规则即可,例如多个参数T1,T2,T3等
abstract class genBaseClass<T1, T2> //定义了两个参数的泛型类
{
public T1[] str; //定义一个泛型数组
public T2[] ind;
//定义一个索引属性
public T1 this[int index]
{
set { str[index] = value; }
get { return str[index]; }
}
//定义一个获取数组长度的属性
public int length
{
get { return str.Length; }
}
// 构造函数
public genBaseClass(int index)
{
str = new T1[index];
ind = new T2[index];
}
}
//定义派生的泛型类
class genClass<T>: genBaseClass<T, int> //如果基类和派生类中同时出现了某个类型参数,那么二者的含义是一致的,他们只带同一个开放类型,而最终在使用时会被同一个封闭类型取代。
{
public genClass(int index):base(index) //如果泛型定义了多个参数,除了泛型类本身,其封闭的构造类型和开放的构造类型都可以作为其他泛型类的基类。(继承构造类型)
{
for (int i = 0; i <length ; i++)
{
ind[i] = i;
}
}
//派生类中定义一个output方法
public void output()
{
for(int i=0; i<length; i++)
{
Console.WriteLine(str[i].ToString());
}
}
}
class Program
{
static void Main(string[] args)
{
//实例化类对象
genClass<String> gc = new genClass<string>(6);
//添加元素的过程
gc[0] = "first";
gc[1] = "Second";
gc[2] = "third";
gc[3] = "fourth";
gc[4] = "fifth";
gc[5] = "sixth";
//调用方法,遍历元素
gc.output();
Console.WriteLine("泛型类继承泛型类成功");
Console.ReadLine();
}
}
}
System.Collections.Generics下面定义了一下7个接口
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _10_泛型接口的使用
{
//普通的接口
public interface IMyinterface { }
//带有一个参数的泛型接口
public interface IMyinterface<T> { }
//带两个参数的泛型接口
public interface IMyinterface<T1, T2> { }
public interface IRelation<T1,T2>
{
int Forward(T1 forward); //方法只提供标识,不提供实现体
int After(T2 after);
T1 GetForware(int index);//泛型接口所定义的类型参数可以在其方法成员中作为参数或返回类型来使用(此命令行定义的方法返回的参数类型为T1)
void GetAfter(int index, out T2 after); //第一个参数为整型参数,第二个参数为输入类型的泛型参数(out使用见下面链接)
void change(ref T1 forward, ref T2 after); //关于ref的使用,见下面链接
}
class Program
{
static void Main(string[] args)
{
}
}
}
八 C#方法
namespace _11_定义泛型方法
{
//定义普通类
public class myclass
{
//定义泛型方法
public bool Contains<T>(T[] TArry, T TValue) //此方法用于判定数组中是否包含某个元素,所以定义返回bool类型的泛型方法
{
//遍历元素
foreach(T t in TArry) //也可以用来在方法的执行代码中定义局部变量
{
//判断是否存在TValue
if (t.Equals(TValue))
return true; //存在返回true
}
return false; //不存在返回false
}
//所定义的类型参数及可以作为方法的参数类型和返回类型,
public T Contains<T,T1,T2,A>(T[] TArry, T TValue) //此方法用于判定数组中是否包含某个元素,所以定义返回bool类型的泛型方法
{
//此处只是说明多个类型参数,且类型参数不一定要用T表示,也可以用a,b,cd等字符标识,实现体没有任何意义
T mytypevalue = TValue;
return mytypevalue;
}
}
class Program
{
static void Main(string[] args)
{
}
}
}
在程序中调用泛型方法有两种方式
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _11_泛型方法的调用
{
public class myclass
{
//泛型方法实现,数组中是否包含某一元素
public bool Contains<T>(T[] TArray, T TValue)
{
foreach(T t in TArray)
{
if (t.Equals(TValue)) return true;
}
return false;
}
}
class Program
{
static void Main(string[] args)
{
int[] myint = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
myclass mc = new myclass();
bool mybool;
int testInt = 50;
//完整调用
Console.WriteLine("完成调用");
mybool = mc.Contains<int>(myint, testInt);
if (mybool) Console.WriteLine("数组中包含有元素" + testInt);
else Console.WriteLine("数组中不包含元素" + testInt);
Console.ReadKey();
//简写调用
Console.WriteLine("简写调用");
bool mybool2;
mybool2 = mc.Contains(myint, testInt);
if (mybool2) Console.WriteLine("数组中包含有元素" + testInt);
else Console.WriteLine("数组中不包含元素" + testInt);
Console.ReadKey();
}
}
}