码迷,mamicode.com
首页 > Web开发 > 详细

.NET编程01(泛型)

时间:2017-09-11 23:34:03      阅读:446      评论:0      收藏:0      [点我收藏+]

标签:继承   约束   .net   入参   void   sleep   类型   父类   代码   

一:Object 类型:一切类型的父类,通过继承,子类拥有父类一切属性和行为;任何父类出现的地方,都可以用子类来代替;

用一个方法来完成多个方法做的事

/// <summary>
    /// 普通方法类
    /// </summary>
    public class CommonMethod
    {
        /// <summary>
        /// 打印个int值
        /// </summary>
        /// <param name="iParameter"></param>
        public static void ShowInt(int iParameter)
        {
            Console.WriteLine("This is {0},parameter={1},type={2}",
                typeof(CommonMethod).Name, iParameter.GetType().Name, iParameter);
        }

        /// <summary>
        /// 打印个string值
        /// </summary>
        /// <param name="sParameter"></param>
        public static void ShowString(string sParameter)
        {
            Console.WriteLine("This is {0},parameter={1},type={2}",
                typeof(CommonMethod).Name, sParameter.GetType().Name, sParameter);
        }

        /// <summary>
        /// 打印个object值
        /// </summary>
        /// <param name="oParameter"></param>
        public static void ShowObject(object oParameter)
        {
            Console.WriteLine("This is {0},parameter={1},type={2}",
                typeof(CommonMethod), oParameter.GetType().Name, oParameter);

        }

Typeof():用来获取某个类型

缺点:

第一:object是应用类型的,所以把值类型的参数传入ShowObject()方法时,就会存在装箱和拆箱,影响性能

第二:传入参数里面的属性值无法被访问到

第三:涉及到类型安全的问题

 

二:泛型(不属于语法糖,是ClR升级后才支持的语法)

用途:对于不同类型的参数,具有相同行为的时候,希望代码能重用起来,这时候使用泛型

原理: /// 延迟申明:申明方法的时候并没有指定参数类型(实际存在两个参数:T是类型参数,oParameter是真实参数),而是等到使用的时候在指定

   /// 延迟思想:推迟一切可以推迟的

     /// 编译的时候,类型参数编译为占位符,在程序真实运行的时候,JIT进行即时编译替换为真实类型

public class GenericMethod

{

  /// <summary>
        /// 第一:泛型方法(方法名字后面带上尖括号,类型参数),尖括号类可以是任何没定义的任何字母或者类型,不要写关键字,不要把定义好的类写在里面

        /// </summary>
        /// <param name="oParameter"></param>
        public static void Show<T>(T oParameter)
        {
            Console.WriteLine("This is {0},parameter={2},type={1}",
                typeof(CommonMethod), oParameter.GetType().Name, oParameter);

        }

}

  class Program
    {
        static void Main(string[] args)
        {

    int iValue = 123;

             object ovalue=new object();

 

    //第一:泛型方法调用

    GenericMethod.Show<int>(ivalue);

    GenericMethod.Show(ivalue);//不指定类型参数,编译器自动推算

    GenericMethod.Show<string>(ivalue);//此时报错,<类型参数>参数类型:(ivalue)的类型必须吻合

         GenericMethod.Show<object>(ovalue);


        }

}

三:泛型类/接口

//泛型类

public class GenericClass<M,T,S>

{

     public void Show(M m){}//可以作为参数

 public  T get(){}//可以作为返回值

}

//泛型接口

publuc interInface IStudy<T>

{

    T  Study(T t);

}

//泛型委托

public delegate T GetHandler<T>();

 

//普通类

public class Child

          :GenericClass<M,T,S>//报错普通类不能直接继承泛型类

     :GenericClass<int,string,double>//指定类型参数后才可以继承

   :IStudy<T>//报错普通类不能直接实现泛型接口

   :IStudy<string>//指定类型后可以

{

  public string Study(string t){}

}

//泛型类

public class GenericChils<M,T>//等于申明了两个局部类型 M,T

             :GenericClass<M,T,String>//泛型类可以直接继承泛型类

          :IStudy<T>//T和M都可以或者指定一个特定类型,除此之外不行,泛型类可以直接实现泛型接口

{

     T IStudy<T>.Study(T t){}

}

四:泛型约束

public class People

{

  public int Id { get; set; }

  public string Name { get; set; }
        public void Hi(){ }

}

public class Chinese :People:ISports

{

   public void SayHi(){}

        public void Pingpang(){}

}

public interface ISports
    {
        void Pingpang();
    }

public class Constraint

{

      ///基类约束

   /// 1: 基类约束,就可以访问基类的属性和方法
          /// 2:被调用时, 参数必须是基类/子类

    public static void Show<T>(T oParameter) where T:People{}

     //接口约束

   public static void ShowInterface<T>(T oParameter) where T:ISports{}

   ///接口+基类约束

   public static void ShowBasic<T>(T oParameter) where T:People,ISports{}

   public static T Get<T>()

        //where T:Class//应用了类型约束

        //where T:struce//值类型约束

        //where T:new()//无参数构造函数约束

  {

    T t=new T();

    return null;//应用类型默认值

    return default(T):值类型默认值

  }

}

  泛型方法的约束的调用:

 People people = new People()

Chinese chinese = new Chinese()

Constraint.Show<People>(People p)

Constraint.Show(people )

Constraint.Show<Chinese >(Chinese p)

Constraint.Show(chinese )

Constraint.ShowInterface(people)

 

五:泛型的协变/逆变(out/in):只能放在接口或者委托的参数前面,类没有协变逆变

out 协变 convariant 修饰返回值

in 逆变  contravariant 修饰传入参数       IEnumerable<int>    Action<int>

第一:协变

定义两个普通类

public class Bird{public int ID{get;set;}}

public class Sparrow:Bird{public string Name{get;set;}}

 List<Bird> b1list=new List<bird>();------编译正确

List<Bird> B2list=new List<Sparrow>();------编译错误,因为list<Bird>和List<Sparrow>不是父子关系,没有继承关系

但是实际工作中会有这种需要(用父类集合来接受子类的集合)

一般的写法:List<Bird> B3list=new List<Sparrow>().select(c=>(Bird)c).ToList();-----编译正确,类型进行了强转

简单的写法:IEnumerable<Bird> b1=new List<bird>();---------协变

           IEnumerable<Bird> b2=new List<Sparrow>();---------协变(实际上也存在类型的的转换,只不过是编译器来做,减少了代码量)

以上写法采用协变使用系统提供的IEnumerable<out T>

public interface IEnumerable<out T> : IEnumerable  ------ 系统对IEnumerable<out T>的定义

使用List来接受子类集合会报错是因为,系统本身本没有对list进行协变定义

public class List<T>:IList<T>,IEnumerable<T>..........----------- 系统对List<T>的定义 参数没有Out

原因:List出现在.net2.0版本,而IEnumerable<out T>出现在C#4.0版本,两个不是属于同一个时期出现

 

自定义协变接口

Public interface ICustomerListOut<out T>

{

   T Get();-----正确

      void Show(T t)----报错,T不能作为传入参数,只能是返回结果;

}

//类没有协变逆变

public class CustomerListOut<T>:ICustomerListOut<T>

{

    public T Get(){return default(T);}

}

使用:

ICustomerListOut<Bird> b=new CustomerListOut<Bird>();

ICustomerListOut<Bird> b=new CustomerListOut<Sparrow>();

 

第二:逆变

自定义逆变接口

Public interface ICustomerListOut<in T>

{

   //T Get();-----报错,T只能作为传入参数,不能是返回结果;

      void Show(T t)----正确

}

public class CustomerListOut<T>:ICustomerListOut<T>

{

    public void Show(T t){}

}

使用:

 ICustomerListIn<Sparrow> customerList2 = new CustomerListIn<Sparrow>();
 ICustomerListIn<Sparrow> customerList1 = new CustomerListIn<Bird>();

第三:逆变+协变(实际工作中使用很少,一般使用系统很少自己定义,系统自带Func<in T,out Tresult>)

  public interface IMyList<in inT, out outT>
    {
        void Show(inT t);
        outT Get();
        outT Do(inT t);
    }

    public class MyList<T1, T2> : IMyList<T1, T2>
    {

        public void Show(T1 t)
        {
            Console.WriteLine(t.GetType().Name);
        }

        public T2 Get()
        {
            Console.WriteLine(typeof(T2).Name);
            return default(T2);
        }

        public T2 Do(T1 t)
        {
            Console.WriteLine(t.GetType().Name);
            Console.WriteLine(typeof(T2).Name);
            return default(T2);
        }
    }

使用:

     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>();//协变+逆变

 

第六:泛型的缓存

一般采用字典缓存:定义一个静态属性

    /// <summary>
    /// 字典缓存:静态属性常驻内存
    /// </summary>
    public class DictionaryCache
    {
        private static Dictionary<string, string> _TypeTimeDictionary = null;
        static DictionaryCache()
        {
            Console.WriteLine("This is DictionaryCache 静态构造函数");
            _TypeTimeDictionary = new Dictionary<string, string>();
        }
        public static string GetCache<T>()
        {
            Type type = typeof(T);
            if (!_TypeTimeDictionary.ContainsKey(type.Name))
            {
                _TypeTimeDictionary[type.Name] = string.Format("{0}_{1}", typeof(T).FullName, DateTime.Now.ToString("yyyyMMddHHmmss.fff"));
            }
            return _TypeTimeDictionary[type.Name];
        }
    }

第二:泛型缓存

原理:利用泛型每次在运行时Jit即时编译生成不同的副本

使用场景:用来保存固定数据,适合不同类型,需要缓存一份数据的场景,

优点:效率高

缺点:不能清除被回收

 /// <summary>
    /// 每个不同的T,在运行的时候JIT都会生成一份不同的副本,用于保存不同的T
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class GenericCache<T>
    {
        static GenericCache()
        {
            Console.WriteLine("This is GenericCache 静态构造函数");
            _TypeTime = string.Format("{0}_{1}", typeof(T).FullName, DateTime.Now.ToString("yyyyMMddHHmmss.fff"));
        }

        private static string _TypeTime = "";

        public static string GetCache()
        {
            return _TypeTime;
        }
    }

调用:

 for (int i = 0; i < 5; i++)
            {
                Console.WriteLine(GenericCache<int>.GetCache());
                Thread.Sleep(10);
                Console.WriteLine(GenericCache<long>.GetCache());

  }

.NET编程01(泛型)

标签:继承   约束   .net   入参   void   sleep   类型   父类   代码   

原文地址:http://www.cnblogs.com/fairyzhang/p/7502444.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!