1. 泛型Generic 1.1 引入泛型:延遲聲明 泛型方法聲明時,並未寫死類型,在調用的時候再指定類型。 延遲聲明:推遲一切可以推遲的。 1.2 如何聲明和使用泛型 泛型方法:方法名稱後面加上尖括弧,裡面是類型參數 類型參數實際上就是一個類型T聲明,方法就可以用這個類型T了。 如下所示: pub ...
1. 泛型Generic
1.1 引入泛型:延遲聲明
泛型方法聲明時,並未寫死類型,在調用的時候再指定類型。
延遲聲明:推遲一切可以推遲的。
1.2 如何聲明和使用泛型
泛型方法:方法名稱後面加上尖括弧,裡面是類型參數
類型參數實際上就是一個類型T聲明,方法就可以用這個類型T了。
如下所示:
public static void Show<T>(T t)
{
Console.WriteLine($"This is {typeof(CustomMethod)},paramater={t.GetType().Name},value={t}");
}
1.3 泛型的好處和原理
泛型方法性能跟普通方法一致,泛型聲明方法時,並未寫死類型,T是什麼類型,只有在調用的時候才知道,一個方法能滿足不同類型。
1.4 泛型類、泛型方法、泛型介面、泛型委托
1.4.1 泛型類型
一個類滿足不同類型的需求
具體如下:
public class BaseModel
{
public int Id { get; set; }
}
public class GenericClass<T>
where T:BaseModel//為泛型基類約束
{
}
1.4.2 泛型方法
一個方法滿足不同類型的需求
具體如下:
public static void Show<T>(T t)
{
Console.WriteLine($"This is {typeof(CustomMethod)},paramater={t.GetType().Name},value={t}");
}
1.4.3 泛型介面
一個介面滿足不同類型的需求
//泛型介面
public interface IGenericInterface<T>
{
public void SayHi(T t);
}
1.4.4 泛型委托
一個委托滿足不同類型的需求
public delegate void Do<T>(T t);
1.5 泛型約束
沒有約束,泛型會很局限。主要有5中泛型的約束。如下:
1.5.1 基類約束
Where T:BaseModel
可以把BaseModel當作基類
只有該類型的對象或從該類型派生出的對象,可被用作類型參數。(密封類約束的不行,因為沒有意義。)
//基類
public class BaseModel
{
public int Id { get; set; }
}
//泛型類
public class GenericClass<T>
where T:BaseModel//為泛型基類約束
{
}
調用:
GenericConstraint.Show<BeiJing>(new BeiJing());
1.5.2 引用類型約束
//引用類型約束
public static T Get<T>() where T:class
{
return default(T);//default是關鍵字,根據類型T返回對應的預設值
}
調用:
GenericConstraint.Get<Person>(new Person());
1.5.3 值類型約束
//值類型約束
Public static D GetD<D>() where D:struct
{
return default(D);
}
調用:
GenericConstraint.GetD<int>(116);
1.5.4 無參數構造函數
//無參數構造函數約束
Public static S GetS<S>()
where S: new()//無餐構造函數約束
{
return new S();
}
調用:
GenericConstraint.GetS<Chinese>();
1.5.5 介面約束
//介面約束
public static void Show2<T>(T t) where T : ISports
{
t.Basketball();
}
調用:
GenericConstraint.Show2<USA>(new USA());
1.6 協變、逆變
所謂協變、逆變都是跟泛型有關的(多用在介面)。
1.6.1 協變
修飾返回值
讓右邊用子類,讓泛型用起來更方便(子類轉父類)
Out修飾,協變後只能是返回結果,不能做參數
IEnumerable<Bird> birdList=new List<Sparrow>();
//out 協變,只能是返回結果(子類轉父類)
public interface ICustomerListOut<out T>
{
T Get();
}
public class CustomerListOut<T>:ICustomerListOut<T>
{
public T Get()
{
return default(T);
}
}
ICustomerListOut<Bird> list2 = new CustomerListOut<Sparrow>();
Func<Bird> func = new Func<Sparrow>(() => null);
IEnumerable<Bird> list3 = new List<Sparrow>();
1.6.2 逆變
修飾傳入參數
讓右邊可以用父類,讓泛型用起來更方便(父類轉子類)
In修飾,逆變後只能當作參數
//in 逆變 只能是輸入參數(父類轉子類)
public interface ICustomerListIn<in T>
{
void Show(T t);
}
public class CustomerListIn<T>:ICustomerListIn<T>
{
public void Show(T t)
{
Console.WriteLine(t.GetType().Name);
}
}
//逆變
ICustomerListIn<Sparrow> list1 = new CustomerListIn<Bird>();
Action<Sparrow> action = new Action<Bird>((i) => { });
public interface IMyList<in inT,out outT>
{
void Show(inT t);
outT Get();
outT Do(inT t);
}
public class MyList<T, T1> : IMyList<T, T1>
{
public void Show(T t)
{
Console.WriteLine(t.GetType().Name);
}
public T1 Get()
{
Console.WriteLine(typeof(T1).Name);
return default(T1);
}
public T1 Do(T t)
{
Console.WriteLine(t.GetType().Name);
Console.WriteLine(typeof(T1).Name);
return default(T1);
}
}
IMyList<Sparrow, Bird> myList1 = new MyList<Sparrow, Bird>();
IMyList<Sparrow, Bird> myList2 = new MyList<Sparrow, Sparrow>();//協變
IMyList<Sparrow, Bird> myList3 = new MyList<Bird, Bird>();//逆變
IMyList<Sparrow, Bird> myList4 = new MyList<Bird, Sparrow>();//逆變+協變
1.7 泛型緩存
泛型緩存,每個類型都會生成一個不同的副本(適合不同類型需要緩存一份數據的場景)
public class GenericCache<T>
{
private static string _TypeTime = "";
static GenericCache()
{
Console.WriteLine("This is GenericCache 靜態構造函數");
_TypeTime = $"{typeof(T).FullName}_{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}";
}
public static string GetCache()
{
return _TypeTime;
}
}
/// <summary>
/// 字典緩存:靜態屬性常駐記憶體
/// </summary>
public class DictionaryCache
{
private static Dictionary<Type, string> _TypeTimeDictionary = null;
static DictionaryCache()
{
Console.WriteLine("This is DictionaryCache 靜態構造函數");
_TypeTimeDictionary = new Dictionary<Type, string>();
}
public static string GetCache<T>()
{
Type type = typeof(Type);
if (!_TypeTimeDictionary.ContainsKey(type))
_TypeTimeDictionary[type] = $"{typeof(T).FullName}_{DateTime.Now.ToString("yyyy-MM-dd HH mm:ss")}";
return _TypeTimeDictionary[type];
}
}