System; using System.Collections.Generic; using System.Linq; using System.Text; namespace XNdemo { class Program { static void Main(string[] args) { ISample<ChildClass> child = new Sample<ChildClass>(); ISample < BaseClass > baseclusing ass = child;//协变 ISample<Object> obj = baseclass;//协变 baseclass.Function(new ChildClass()); } } public class BaseClass { public virtual void Print() { Console.WriteLine("in baseClass"); } } public class ChildClass : BaseClass { public override void Print() { Console.WriteLine("in childClass"); } } interface ISample< T> { T Function(T var); } class Sample<T> : ISample<T> where T:BaseClass { public T Function(T var) { Console.WriteLine("work..."); var.Print(); return default(T); } } }
1泛型类中的约束是有顺序的:
class,struct,<base class name>这三种类型的约束必须在第一位
之后是<interface name>约束类型,数量不限
如果有new()约束类型,必须放在最后,并且对应的实参类型必须有一个无参的公共构造函数使用格式
class MyPrinter<T,K>
where K:class
where t:class,Iprinter,new()
{
///约束的次序是有要求的
}
简单约束使用格式:
View Code
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace YShDemo 7 { 8 class Program 9 { 10 static void Main(string[] args) 11 { 12 Customer customer = new Customer(); 13 customer.CreditCardNo = "123456"; 14 customer.Name = "lzhq"; 15 Shop<Customer> shop = new Shop<Customer>(); 16 shop.Print(customer); 17 } 18 } 19 public class Shop<T> 20 where T:Customer//类型参数的约束T必须为customer类或者为其派生类 21 { 22 public void Print(T customer) 23 { 24 Console.WriteLine( customer.CreditCardNo); 25 Console.WriteLine(customer.Name); 26 } 27 28 } 29 public class Customer 30 { 31 public string Name 32 { 33 get; 34 set; 35 } 36 public string CreditCardNo 37 { 38 get; 39 set; 40 } 41 } 42 }
泛型委托:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace FXdelegate 7 8 { 9 delegate TResult PrintDelegate<T,TResult>(T data); 10 class Program 11 { 12 static void Main(string[] args) 13 { 14 PrintDelegate<string, string> p1 = Printer.PrintString; 15 PrintDelegate<int, int> p2 = Printer.PrintInt; 16 PrintDelegate<string, int> p3 = Printer.PrintIntEx; 17 Console.WriteLine(p1("lzhq")); 18 Console.WriteLine(p2(2)); 19 Console.WriteLine(p3("lzhq")); 20 21 } 22 } 23 public class Printer 24 { 25 public static string PrintString(string msg) 26 { 27 Console.WriteLine(msg); 28 return msg; 29 } 30 public static int PrintInt(int msg) 31 { 32 return msg; 33 } 34 public static int PrintIntEx(string msg) 35 { 36 return 0; 37 } 38 } 39 }
泛型方法:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace FXmethod 7 { 8 class Program 9 { 10 static void Main(string[] args) 11 { 12 Printer.Print<int, Data>(2010); 13 Printer.Print<string, Data>("lzhq"); 14 15 16 } 17 } 18 public class Data 19 { 20 public Data() 21 { 22 System.Console.WriteLine("construts Data class"); 23 } 24 } 25 public class Printer 26 { 27 public static TResult Print<T, TResult>(T msg) 28 where TResult : new() 29 { 30 Console.WriteLine(msg); 31 TResult result = new TResult(); 32 return result; 33 } 34 } 35 }
4
在使用泛型接口时期中的泛型参数可以声明为协变参数或者逆变参数
协变:泛型参数定义的类型只能作为方法的返回类型不能作为方法的参数类型,且该类型直接或间接继承接口方法的返回值类型
逆变:泛型参数的类型只能作为接口方法的参数类型不能做为返回值类型,且该类型是接口方法参数类型的基类型。
简单的总结就是:如果泛型参数做为实现接口的类中的方法的返回值类型时就是协变,此时由实现类实例化的对象必须由以返回类型的基类作为泛型参数的接口来引用
如果泛型参数作为实现类的方法的参数使用时,那么实例化的类对象必要由以该参数为基类的派生类的泛型参数 的接口引用。
协变,逆变使用格式:
注:协变和逆变对应的参数类型都必须是引用类型时才有意义,如果是值类型就必须使用接口的相同的值类型参数做为左侧指向变量。
泛型接口:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace InterfaceDemo 7 { 8 class Program 9 { 10 static void Main(string[] args) 11 { 12 ILog<string> log1 = new Log<string>(); 13 ILog<int> log2 = new Log<int>(); 14 log1.Error("hello world"); 15 log2.Error(2101); 16 Console.WriteLine(log1.GetCurrentMsg()); 17 } 18 } 19 public interface ILog<T> 20 { 21 void Error(T message); 22 T GetCurrentMsg(); 23 } 24 public class Log<T> : ILog<T> 25 { 26 private T _currentMsg; 27 public void Error(T message) 28 { 29 _currentMsg = message; 30 Console.WriteLine(message); 31 } 32 public T GetCurrentMsg() 33 { 34 return _currentMsg; 35 } 36 37 } 38 }
注意:接口中的成员默认都是public 的不允许重复添加public的访问权限,在运行时会报错,提示接口成员不能添加任何访问修饰权限。