http://www.sufeinet.com/plugin.php?id=keke_group

苏飞论坛

 找回密码
 马上注册

QQ登录

只需一步,快速开始

分布式系统框架(V2.0) 轻松承载百亿数据,千万流量!讨论专区 - 源码下载 - 官方教程

HttpHelper爬虫框架(V2.7-含.netcore) HttpHelper官方出品,爬虫框架讨论区 - 源码下载 - 在线测试和代码生成

HttpHelper爬虫类(V2.0) 开源的爬虫类,支持多种模式和属性 源码 - 代码生成器 - 讨论区 - 教程- 例子

查看: 16219|回复: 0
打印 上一主题 下一主题

[C#语言基础] C#泛型以及泛型抽象类的继承

[复制链接]
跳转到指定楼层
楼主
发表于 2013-10-8 15:11:20 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
泛型
、什么是泛型?
通过泛型可以定义类型安全类,而不会损害类型安全、性能或工作效率

、实例化泛型
1、可以使用任何类型来声明和实例化
2、申明和实例话都必须用一个特定的类型来代替一般类型T
3、例子:
[code=csharp]//原来写法
Public class Stack
{
object[] m_Items;
public void Push(object item)
{...}
public object Pop()
{...}
}
Stack stack = new Stack();
stack.Push(1);
int number = (int)stack.Pop();

//有了泛型后
Public class Stack <T>
{
T[] m_Items;
public void Push(T item)
{...}
public T Pop()
{...}
}
Stack <int> stack = new Stack <int> ();
stack.Push(1);
int number = (int)stack.Pop(); [/code]

:泛型的好处
1、一次性的开发、测试和部署代码,通过任何类型来重用它
2、编译器支持和类型安全
3、不会强行对值类型进行装箱和取消装箱,或者对引用类型进行向下强制类型转换,所以性能得到显著提高。
注:值类型大概可以提高200%,引用类型大概为100%

:多个泛型
1、单个类型可以定义多个泛型

五:泛型别名
1、在文件头部使用using 为特定类型取别名,别名作用范围是整个文件
2、例子
[code=csharp]using List = LinkedList <int,string> ;
class ListClient
{
static void Main(string[] args)
{
List list = new List();
list.AddHead(123, "AAA ");
}
} [/code]

:泛型约束
(1)、派生约束
如:
[code=csharp]public class LinkedList <K,T> where K:IComparable
{
T Find(K key)
{
if (str.Key.CompareTo(key) == 0)//只有实现这个接口才可比较
}
} [/code]

注意:
1、所有的派生约束必须放在类的实际派生列表之后
如:[code=csharp]public class LinkedList <K,T> :IEnumerable <T> where K:IComparable <K>
{...} [/code]
2、一个泛型参数上可以约束多个接口(用逗号分隔)
[code=csharp]public class LinkedList <K,T> where K:IComparable <K> ,IConvertible [/code]
3、在一个约束中最多只能使用一个基类
4、约束的基类不能是密封类或静态类
5、不能将System.Delegate或System.Array约束为基类
6、可以同时约束一个基类以及一个或多个接口,但是该基类必须首先出现在派生约束列表中。
7、C#允许你将另一个泛型参数指定为约束
[code=csharp]public class MyClass <T,U> where T:U
{...} [/code]
8、可以自己定义基类或接口进行泛型约束
9、自定义的接口或基类必须与泛型具有一致的可见性

(2)、构造函数约束
如:
[code=csharp]class Node <K,T> where T:new()
{
} [/code]
注意:
1、可以将构造函数的约束和派生约束结合起来,前提是构造函数的约束出现在约束列表中的最后

(3)、引用/值类型约束
1、可以使用struct约束将泛型参数约束为值类型(如int、bool、enum),或任何自定义结构
2、同样可以使用class约束将泛型参数约束为引用类型
3、不能将引用/值类型约束与基类约束一起使用,因为基类约束涉及到类
4、不能使用结构和默认构造函数约束,因为默认构造函数约束也涉及到类
5、虽然您可以使用类和默认构造函数约束,但是这样做没有任何价值
6、可以将引用/值类型约束与接口约束组合起来,前提是引用/值类型约束出现在约束列表的开头

:泛型和强制类型转换
1、C#编译器只允许将泛型参数隐式转换到Object或约束指定的类型
如:
[code=csharp]interface IS{...}
class BaseClass{...}
class MyClass <T> where T:BaseClass,IS
{
void SomeMethod(T t)
{
IS obj1 = t;
BaseClass obj2 = t;
object obj3 = t;
}
} [/code]
2、编译器允许你将泛型参数显示强制转换到其他任何借口,但不能将其转换到类
[code=csharp]interface IS{...}
class SomeClass{...}
class MyClass <T> //没有约束
{
void SomeMethod(T t)
{
IS obj1 = (IS)t; //可以
SomeClass obj2 = (SomeClass)t //不可以
}
} [/code]
3、可以使用临时的Object变量,将泛型参数强制转换到其他任何类型
[code=csharp]class SomeClass{...}
class MyClass <T>
{
void SomeMethod(T t)
{
object temp = t;
SomeClass obj = (SomeClass)temp;//可以
}
} [/code]
注意:这里只是告诉你这样写是可以的,但是要不要这样写?不要这样写,因为如果t确实没有继承SomeClass编译没错但是运行就会出错
4、解决上面强制转换问题,可以使用is和as运算符进行判断
[code=csharp]public class MyClass <T>
{
public void SomeMethod <T t>
{
if (t is int ){...}
if (t is LinkedList <int,string> ){...}
//如果泛型参数的类型是所查询的类型,则is运算符返回true
string str = t as string;
//如果这写类型兼容,则as将执行强制类型转换,否则将返回null
if (str != null){...}
LinkedList <int,string> list = t as LinkedList <int,string> ;
if (list != null){...}
}
} [/code]

七:继承和泛型
1、在从泛型基类派生,可以提供类型实参,而不是基类泛型参数
public class BaseClass <T> {...}
public class SubClass:BaseClass <int>
2、如果子类是泛型,而非具体的类型实参,则可以使用子类泛型参数作为泛型基类的指定类型
[code=csharp]public class BaseClass <TT> {...}
public class SubClass <T> :BaseClass <T> {...} [/code]
3、在使用子类泛型参数时,必须在子类级别重复在基类级别规定的任何约束
4、基类可以定义其签名使用泛型参数的虚礼方法,在重写它们时,子类必须在方法签名中提供相应的类型。
如:
[code=csharp]public class BaseClass <T>
{
public virtual T SomeMethod()
{...}
}
public class SubClass:BaseClass <int>
{
public override int SomeMethod()
{...}
} [/code]
5、如果该子类是泛型,则它还可以在重写时使用它自己的泛型参数
[code=csharp]public class SubClass <T> :BaseClass <T>
{
public override T SomeMethod()
{...}
} [/code]
6、你可以定义泛型接口、泛型抽象类,甚至泛型抽象方法。
7、不能对泛型参数使用+或+=之类的运算符
[code=csharp]public class Calculator <T>
{
public T Add (T arg1,T arg2)
{
return arg1 + arg2;//错误
}
} [/code]
但是我们可以通过泛型抽象类、接口来实现在个功能,因为实现泛型抽象类、接口我们就已经明确传一个参数了,就可以执行诸如+这样的操作。

八:泛型方法
1、方法可以定义特定于其执行范围的泛型参数
[code=csharp]public class MyClass <T>
{
public void MyMethod <X> (X x)
{...}
} [/code]
2、即使各包含类根本不使用泛型,你也可以定义方法特定的泛型参数
[code=csharp]public class MyClass
{
public void MyMethod <T> (T t)
{...}
} [/code]
注意:该功能只使用于方法,属性,索引器只能使用在类的作用范围中定义的泛型参数。
3、调用泛型方法
[code=csharp]MyClass obj = new MyClass();
obj.MyMethod <int> (3);
也可以这样:
MyClass obj = new MyClass();
obj.MyMethod(3); //该功能称为泛型推理 [/code]
4、泛型方法也可以有自己的泛型参数约束
[code=csharp]pubic class MyClass
{
public void SomeMethod <T> (T t) where T:IComparable <T>
{...}
} [/code]
5、子类方法实现不能重复在父级别出现的约束
[code=csharp]public class BaseClass
{
public virtual void SomeMethod <T> (T t)where T:new()
{...}
}
pubic class SubClass:BaseClass
{
public override void SomeMethod <T> (T t)//不能再有约束
{...}
} [/code]
6、静态方法
静态方法可以定义特定的泛型参数和约束
[code=csharp]public class MyClass <T>
{
public static T SomeMethod <X> (T t,X x)
{...}
}
int number = MyClass <int> .SomeMethod <string> (3, "AAA ");
或者:int mumber = MyClass <int> .SomeMethod(3, "AAA "); [/code]

九:泛型委托
1、在某个类中定义的委托可以利用该类的泛型参数
2、委托也可以定义自己的泛型参数
[code=csharp]1.泛型和泛型强制转换   
   
using System;   
using System.Collections.Generic;   
using System.Text;   
   
namespace VS2005Demo2   
6{   
  
   C# 编译器只允许将泛型参数隐式强制转换到 Object 或约束指定的类型#region  C# 编译器只允许将泛型参数隐式强制转换到 Object 或约束指定的类型   
   public interface ISomeInterface   
   { }   
   class BaseClass   
   { }   
   class MyClass<T> where T : BaseClass, ISomeInterface   
   {   
       void SomeMethod(T t)   
       {   
           ISomeInterface obj1 = t;   
           BaseClass obj2 = t;   
           object obj3 = t;   
       }   
   }   
   #endregion   
  
   编译器允许您将泛型参数显式强制转换到其他任何接口,但不能将其转换到类#region 编译器允许您将泛型参数显式强制转换到其他任何接口,但不能将其转换到类   
   class SomeClass   
   { }   
   //class MyClass1<T>   
   //{   
   //    void SomeMethod(T t)   
   //    {   
   //        ISomeInterface obj1 = (ISomeInterface)t;  //Compiles   
   //        SomeClass obj2 = (SomeClass)t;           //Does not compile   
   //    }   
   //}   
   #endregion   
  
  
   使用临时的 Object 变量,将泛型参数强制转换到其他任何类型#region 使用临时的 Object 变量,将泛型参数强制转换到其他任何类型   
   class MyClass2<T>   
   {   
       void SomeMethod(T t)   
       {   
           object temp = t;   
           SomeClass obj = (SomeClass)temp;   
       }   
   }   
   #endregion   
  
   使用is和as运算符#region 使用is和as运算符   
   public class MyClass3<T>   
   {   
       public void SomeMethod(T t)   
       {   
           if (t is int) { }   
           if (t is LinkedList<int, string>) { }   
           string str = t as string;   
           if (str != null) { }   
           LinkedList<int, string> list = t as LinkedList<int, string>;   
           if (list != null) { }   
       }   
   }   
   #endregion   
  
64}   
  
   
2.继承和泛型   
   
  1using System;   
  2using System.Collections.Generic;   
  3using System.Text;   
  
  5namespace VS2005Demo2   
  6{   
   继承和泛型#region 继承和泛型   
   public class BaseClass<T>   
   { }   
   public class SubClass : BaseClass<int>   
   { }   
  
  
   public class SubClass1<R> : BaseClass<R>   
   { }   
   #endregion   
  
   继承约束#region 继承约束   
   public class BaseClass1<T> where T : ISomeInterface   
   { }   
   public class SubClass2<T> : BaseClass1<T> where T : ISomeInterface   
   { }   
  
   //构造函数约束   
   public class BaseClass3<T> where T : new()   
   {   
       public T SomeMethod()   
       {   
           return new T();   
       }   
   }   
   public class SubClass3<T> : BaseClass3<T> where T : new()   
   { }   
  
   #endregion   
  
   虚拟方法#region 虚拟方法   
   public class BaseClass4<T>   
   {   
       public virtual T SomeMethod()   
       {   
           return default(T);   
       }   
   }   
   public class SubClass4 : BaseClass4<int>   
   {   
       public override int SomeMethod()   
       {   
           return 0;   
       }   
   }   
  
   public class SubClass5<T> : BaseClass4<T>   
   {   
       public override T SomeMethod()   
       {   
           return default(T);   
       }   
   }   
  
   #endregion   
  
   接口、抽象类继承#region 接口、抽象类继承   
   public interface ISomeInterface6<T>   
   {   
       T SomeMethod(T t);   
   }   
   public abstract class BaseClass6<T>   
   {   
       public abstract T SomeMethod(T t);   
   }   
   public class SubClass6<T> : BaseClass6<T>,ISomeInterface6<T>   
   {   
       public override T SomeMethod(T t)   
       { return default(T); }   
   }   
   #endregion   
  
   泛型抽象方法和泛型接口#region 泛型抽象方法和泛型接口   
   //public class Calculator<T>   
   //{   
   //    public T Add(T arg1, T arg2)   
   //    {   
   //        return arg1 + arg2;//Does not compile   
   //    }   
   //    //Rest of the methods   
   //}   
  
   public abstract class BaseCalculator<T>   
   {   
       public abstract T Add(T arg1, T arg2);   
       //public abstract T Subtract(T arg1, T arg2);   
       //public abstract T Divide(T arg1, T arg2);   
       //public abstract T Multiply(T arg1, T arg2);   
   }   
   public class MyCalculator : BaseCalculator<int>   
   {   
       public override int Add(int arg1, int arg2)   
       {   
           return arg1 + arg2;   
       }   
       //Rest of the methods   
   }   
  
   public interface ICalculator<T>   
   {   
       T Add(T arg1, T arg2);   
       //Rest of the methods   
   }   
   public class MyCalculator1 : ICalculator<int>   
   {   
       public int Add(int arg1, int arg2)   
       {   
           return arg1 + arg2;   
       }   
       //Rest of the methods   
   }   
   #endregion   
  
120}   
  
   
3.泛型方法   
   
  1using System;   
  2using System.Collections.Generic;   
  3using System.Text;   
  
  5namespace VS2005Demo2   
  6{   
  
   泛型方法#region 泛型方法   
   public class MyClass   
   {   
       public void MyMethod<T>(T t)   
       { }   
   }   
  
   public class Class3   
   {   
       public void Test()   
       {   
           MyClass obj = new MyClass();   
           obj.MyMethod<int>(3);   
  
           obj.MyMethod(3);   
       }   
   }   
   #endregion   
  
   编译器无法只根据返回值的类型推断出类型#region 编译器无法只根据返回值的类型推断出类型   
   public class MyClass1   
   {   
       public T MyMethod<T>()   
       { return default(T); }   
   }   
  
   public class Class31   
   {   
       public void Test()   
       {   
  
           MyClass1 obj = new MyClass1();   
           int number = obj.MyMethod<int>();   
       }   
   }   
   #endregion   
  
   泛型方法约束#region 泛型方法约束   
   public class Class32   
   {   
       public T MyMethod<T>(T t) where T : IComparable<T>   
       { return default(T); }   
   }   
   #endregion   
  
   泛型虚拟方法#region 泛型虚拟方法   
   public class BaseClass33   
   {   
       public virtual void SomeMethod<T>(T t)   
       { }   
   }   
   public class SubClass33 : BaseClass33   
   {   
       public override void SomeMethod<T>(T t)   
       {   
           base.SomeMethod<T>(t);   
       }   
   }   
  
   public class BaseClass34   
   {   
       public virtual void SomeMethod<T>(T t) where T : new()   
       { }   
   }   
   public class SubClass34 : BaseClass34   
   {   
       public override void SomeMethod<T>(T t)// where T : IComparable<T>   
       { }   
   }   
  
   public class BaseClass35   
   {   
       public virtual void SomeMethod<T>(T t)   
       { }   
   }   
   public class SubClass35 : BaseClass35   
   {   
       public override void SomeMethod<T>(T t)   
       {   
           base.SomeMethod<T>(t);   
           base.SomeMethod(t);   
       }   
   }   
   #endregion   
  
   泛型静态方法#region 泛型静态方法   
   public class MyClass36<T>   
   {   
       public static T SomeMethod(T t)   
       { return default(T); }   
   }   
  
   public class Class36   
   {   
       public void Test()   
       {   
           int number = MyClass36<int>.SomeMethod(3);   
       }   
   }   
  
   public class MyClass37<T>   
   {   
       public static T SomeMethod<X>(T t, X x)   
       { return default(T); }   
   }   
   public class Class37   
   {   
       public void Test()   
       {   
           int number = MyClass37<int>.SomeMethod<string>(3, "AAA");   
           int number1 = MyClass37<int>.SomeMethod(3, "AAA");   
       }   
   }   
  
   public class MyClass38   
   {   
       public static T SomeMethod<T>(T t) where T : IComparable<T>   
       {  return default(T); }   
   }   
  
   #endregion   
129}   
  
   
4.泛型委托   
   
1using System;   
2using System.Collections.Generic;   
3using System.Text;   
  
5namespace VS2005Demo2   
6{   
   泛型委托#region 泛型委托   
   public class MyClass40<T>   
   {   
       public delegate void GenericDelegate(T t);   
       public void SomeMethod(T t)   
       { }   
   }   
  
   public class MyClassTest40   
   {   
       public void Tests()   
       {   
           MyClass40<int> obj = new MyClass40<int>();   
           MyClass40<int>.GenericDelegate del;   
  
           del = new MyClass40<int>.GenericDelegate(obj.SomeMethod);   
           del(3);   
  
           //委托推理   
           del = obj.SomeMethod;   
  
       }   
   }   
   #endregion   
  
   委托泛型参数#region 委托泛型参数   
   public class MyClass41<T>   
   {   
       public delegate void GenericDelegate<X>(T t, X x);   
   }   
  
   //外部委托   
   public delegate void GenericDelegate<T>(T t);   
  
   public class MyClass42   
   {   
       public void SomeMethod(int number)   
       { }   
   }   
  
   public class MyClassTest42   
   {   
       public void Test()   
       {   
           MyClass42 obj = new MyClass42();   
           GenericDelegate<int> del;   
           //del = new GenericDelegate<int>(obj.SomeMethod);   
  
           del = obj.SomeMethod;   
           del(3);   
  
       }   
   }   
  
   #endregion   
  
   委托泛型参数#region 委托泛型参数   
   public delegate void MyDelegate<T>(T t) where T : IComparable<T>;   
   #endregion   
  
   事件#region 事件   
  
   public delegate void GenericEventHandler<S, A>(S sender, A args);   
      
   public class MyPublisher   
   {   
       public event GenericEventHandler<MyPublisher, EventArgs> MyEvent;   
       public void FireEvent()   
       {   
           MyEvent(this, EventArgs.Empty);   
       }   
   }   
  
   public class MySubscriber<A> //Optional: can be a specific type   
   {   
       public void SomeMethod(MyPublisher sender, A args)   
       { }   
   }   
   public class MyClassTest43   
   {   
       public void Test()   
       {   
           MyPublisher publisher = new MyPublisher();   
           MySubscriber<EventArgs> subscriber = new MySubscriber<EventArgs>();   
           publisher.MyEvent += subscriber.SomeMethod;   
       }   
   }   
   #endregion   
95}[/code]


1. 开通SVIP会员,免费下载本站所有源码,不限次数据,不限时间
2. 加官方QQ群,加官方微信群获取更多资源和帮助
3. 找站长苏飞做网站、商城、CRM、小程序、App、爬虫相关、项目外包等点这里
您需要登录后才可以回帖 登录 | 马上注册

本版积分规则

QQ|手机版|小黑屋|手机版|联系我们|关于我们|广告合作|苏飞论坛 ( 豫ICP备18043678号-2)

GMT+8, 2024-11-8 14:01

© 2014-2021

快速回复 返回顶部 返回列表