zoukankan      html  css  js  c++  java
  • C# 泛型详解---进阶编程(七)

    今天我们来学习在C#的泛型技巧,传统的课本都在讲解什么是泛型,然后列举一大堆代码示例告诉你什么是泛型,今天我们就来聊聊更加本质的东西,我为什么要用泛型?它是来解决什么问题的?底层原理是什么?

    简单来说,泛型解决的是什么问题呢?算法重用和提升性能的。

    最最经典的例子是什么?就是微软支持的List<T>类型,想必绝大多的程序员都是使用过这个类的。如果没有这个类,我们可以想象下,如果要你开发一个算法类,支持对数组的长度动态扩展的,还支持一些普遍的数组操作的话。你会怎么写?

    比如我要写  int 数据类型的数组操作功能,写了一遍的 ListInt 类,如果这时候我们需要写一个 float 类型的数组操作对象,我们又得写一遍 ListFloat, 也就是说,每用到一个新的类型的时候,都需要写一遍类,而这之间的代码绝大部分都是相似的。

    你可能会提出我搞一个 ListObject 类就可以了,这样就可以满足所有的情况了,恭喜你,这真的是个很不错的想法,无论你的类型是什么?都会转换为object进行数组的操作,这样只要写一套代码就可以了。只是,当你用了一段时间之后,它会碰到2个比较麻烦的问题

    1. 我实例化了 ListObject 类,Add了很多了int类型的数据,我现在要获取所有的int类型的数组,比如int[],这个比较麻烦,需要对所有object数据进行强制转换。数组的长度比较大的时候,这时候性能就很差,为什么说c和c++性能高,都是地址基于地址的操作,没有类型转换一说。

    2. 我实例化了 ListObject 类,Add了很多了int类型的数据,但是我在用的时候,很容易就误以为是float类型的,从而转换失败,降低了开发的效率。

    这时候我们就要让泛型出场了,List<T>类型,将数组一般的操作逻辑都进行了封装,add,remove,insert,clear,等等操作。当你需要使用int类型的时候,就可以定义List<int>的对象,当你需要short类型的时候,就可以定义List<short>对象,而且不用再转换来转换去了。

    似乎除了上述的情况需要泛型外,似乎我们实际中已经不需要泛型了,答案当然是否定的、

    假设,我们需要编写一个公共的方法。是对数组操作的,比如我们会写一个方法,将数组扩充到指定长度

            /// <summary>
            /// 将一个数组进行扩充到指定长度,或是缩短到指定长度 ->
            /// Extend an array to a specified length, or shorten to a specified length or fill
            /// </summary>
            /// <typeparam name="T">数组的类型</typeparam>
            /// <param name="data">原先数据的数据</param>
            /// <param name="length">新数组的长度</param>
            /// <returns>新数组长度信息</returns>
            public static T[] ArrayExpandToLength<T>( T[] data, int length )
            {
                if (data == null) return new T[length];
    
                if (data.Length == length) return data;
    
                T[] buffer = new T[length];
    
                Array.Copy( data, buffer, Math.Min( data.Length, buffer.Length ) );
    
                return buffer;
            }
    

    这么来看,这个就特别是否写成泛型,和类型无关的情况。

    之前是数组的例子,我们再来看看另一个实际的例子。我们先看看代码:

        /// <summary>
        /// 操作结果的泛型类,允许带一个用户自定义的泛型对象,推荐使用这个类
        /// </summary>
        /// <typeparam name="T">泛型类</typeparam>
        public class OperateResult<T> : OperateResult
        {
            #region Constructor
    
            /// <summary>
            /// 实例化一个默认的结果对象
            /// </summary>
            public OperateResult( ) : base( )
            {
            }
    
            /// <summary>
            /// 使用指定的消息实例化一个默认的结果对象
            /// </summary>
            /// <param name="msg">错误消息</param>
            public OperateResult( string msg ) : base( msg )
            {
    
            }
    
            /// <summary>
            /// 使用错误代码,消息文本来实例化对象
            /// </summary>
            /// <param name="err">错误代码</param>
            /// <param name="msg">错误消息</param>
            public OperateResult( int err, string msg ) : base( err, msg )
            {
    
            }
    
            #endregion
    
            /// <summary>
            /// 用户自定义的泛型数据
            /// </summary>
            public T Content { get; set; }
        }
    

    当你的自定义类需要携带一个数据时,而这个数据可能是任意类型的时候,这时候可以使用泛型。比如这里的 OperateResult<int> 就是非常好的例子。可以用来携带任意的自定义的数据。甚至是数组

    OperateResult<List<int>> 这样也是可以的。

    未完待与

     

  • 相关阅读:
    CentOS6.8上Docker的安装
    IDE- VS Code-插件-Golang
    Tool-Docker-First exploration
    C++-Code-Time Transfer-Windows FILETIME(1601) To 1970 UTC
    Tool-git-command-入门笔记[慕课网-五月的夏天]
    C++-当表达式中同时存在有符号和无符号的类型时,有符号类型先转为无符号参与计算
    C语言-C语言程序设计-Practice code
    C语言-C语言程序设计-Function-strcpy
    C语言-C语言程序设计-Function-fopen
    C语言-C语言程序设计-Application-逆波兰计算器
  • 原文地址:https://www.cnblogs.com/dathlin/p/10666628.html
Copyright © 2011-2022 走看看