c#泛型编程

沪马农 沪马农     2022-08-24     149

关键词:

1.泛型的概念

    C#中的泛型与C++中的模板类似,泛型是实例化过程中提供的类型或类建立的。泛型并不限于类,还可以创建泛型接口、泛型方法,甚至泛型委托。这将极大提高代码的灵活性,正确使用泛型可以显著缩短开发时间。与C++不同的是,C#中所有操作都是在运行期间进行的。

2.使用泛型

  •  可空类型

       值类型必须包含一个值,它们可以在声明之后,赋值之前,在未赋值状态下存在,但不能以任何方式使用,而引用类型可以为null。有时让值类型为空是很有用的,泛型提供了使用System.Nullable<T>使值类型为空的一种方式。如下代码:

    private Nullable<int> _nullableInt;

    则可以为_nullableInt赋为null,如下:

    _nullableInt = null;

可空类型非常有用,以致于C#中加入了语法:

int? _nullableIntSecond;

  • System.Collections.Generic 名称空间

    这个名称空间用于处理集合的泛型类型,使用的非常频繁。将以List<T>和Dictionary<K,V>为例介绍这些类,以及和它们配合使用的接口和方法。

        1.List<T>

        List<T>泛型集合类更加快捷,更易于使用,创建T类型对象的集合需要一下方法:

        List<string> _myCollection = new List<string>();

        将创建T为String的List集合。

        可以在代码中去查看List<T>所支持的方法,这里不再赘述。

       2.对泛型列表进行排序和搜索

        对泛型列表进行排序和搜索与和其它列表进行排序和搜索是一样的,如下为实例代码:

            

public class NumberCollection : List<int>
    {
        public NumberCollection(IEnumerable<int> initialNums)
        {
            foreach (var num in initialNums)
            {
                Add(num);
            }
        }

        public NumberCollection()
        {
            for (int i=0;i < 10;++i)
            {
                Add(i);
            }
        }

        public void Print()
        {
            foreach (var num in this)
            {
                Console.WriteLine(num);
            }

            Console.Read();
        }
    }
public static class NumberCollectionDelegate
    {
        public static int Compare(int i,int j)
        {
            if (i > j)
            {
                return -1;
            }
            else if (i < j)
            {
                return 1;
            }
            return 0;
        }

        public static bool Find(int i)
        {
            if (i %2 == 0)
            {
                return true;
            }

            return false;
        }

         public static Comparison<int> CopmareDelegate = new Comparison<int>(Compare);


         public static Predicate<int> Predicate = new Predicate<int>(Find);


    }
var numColleciton = new NumberCollection();
numColleciton.Print();
numColleciton.Sort(NumberCollectionDelegate.CopmareDelegate);
numColleciton.Print();
var newNumCollection = new NumberCollection(numColleciton.FindAll(NumberCollectionDelegate.Predicate));
newNumCollection.Print();
Console.ReadLine();

如上代码,首先定义了NumberCollection继承自List<int>,定义了Print方法用来输出集合中所有的值,类NumberCollectionDelegate中定义了Compare方法,以及Find方法,Compare方法用于对集合进行降序排序(为什么这么写是降序排序请关注另一篇文章),Find方法用于选择集合中为偶数的值。在实例的使用中,首先对集合中的元素进行了降序排序,后选择集合中为偶数的值组成新的集合,当然上述比较与查找用法可以简化为以下用法:

numColleciton.Sort(NumberCollectionDelegate.Compare);

var newNumCollection = new NumberCollection(numColleciton.FindAll(NumberCollectionDelegate.Find));

这样就不需要显示引用Comparison<int>类型了,但是在使用时仍然会隐式创建Comparison<int>实例,对于比较也是同样的。在许多情况下,都可以使用方法组以这种方式隐式的创建委托,使代码变的更容易读取。

3.Dictionary<K,V>

    这个类型可以定义键值对的集合,这个类型需要实例化两个类型,分别用于键和值,以表示集合中的各个项。可以使用强类型化的Add方法添加键值对,如下。

Dictionary<string, int> stringIntDictionary = new Dictionary<string, int>();
stringIntDictionary.Add("Tom", 1);
stringIntDictionary.Add("Lucy", 2);
stringIntDictionary.Add("Lily", 3);

可以直接访问Dicitionary中的keys和Values属性值:

foreach (var key in stringIntDictionary.Keys)
{
Console.WriteLine(key);
}

foreach (var value in stringIntDictionary.Values)
{
Console.WriteLine(value);
}

同样可以迭代集合中每一项,如下:

foreach (KeyValuePair<string,int> item in stringIntDictionary)
{
Console.WriteLine("{0} = {1}", item.Key, item.Value);
}

对于Dictionary<K,V>需要注意的一点是,每个项的键都必须式唯一的。如果要添加的项与已存在的项的键值相同,则会抛出异常。

3.定义泛型

    1.定义泛型类

         要创建泛型类,只需在类定义中包括尖括号:

class MyGenericClass<T>
{
}

其中T可以是任意标识符,只需要遵循C#命名规则即可,但一般只使用T。

泛型类可以在其定义中包含任意多个类型,它们用逗号分开,例如:

class MyGenericClass<T1,T2,T3>
{
}

定义了这些类型之后,就可以在类定义中像使用其它类型那样使用它们,如下

class MyGenericClass<T1,T2,T3>
    {
        private T1 _object;

        public MyGenericClass(T1 item)
        {
              _object = item;
        }

        public T1 InnerT1Object
        {
            get
            {
                return _object;
            }
        }
    }

注意不能假定使用了什么类型,例如:

_object = new T1();

因为此刻不知道T1是什么,也就不能使用它的构造函数,可能T1就没有构造函数,或者没有可公共访问的构造函数。因此要对泛型进行实际的操作需要更多了解其使用的类型。

  • default关键字

    要确定用于创建泛型类型的实例,需要了解一个最基本的情况,它是引用类型还是值类型,若不了解这个情况就不能直接对变量赋予null值。此时default关键字就派上了用场:

_object = default(T1);

如果_object是引用类型就给引用类型赋为null值,如果为值类型就给它赋为默认值。对于数字类型默认值为0,对于结构,按照相同的规则对它们进行赋值。default关键字允许对必须使用的类型进行更多的操作,为了进行更多的操作,必须对使用的类型进行更多的约束。

  • 约束类型

    前面使用的类型称为无绑定类型,因为没有对它们进行任何约束,而通过约束可以限定用于泛型的类型。在类定义中,可以使用where关键字,来限定用于泛型的类型,如下:

class MyGenericClass<T1,T2,T3> where T1 : constraint

其中constraint定义了约束,可以用这种能方式定义很多约束,每个约束之间用逗号分开。还可以使用多个where语句,定义泛型类型需要的任意类型或所有类型上的约束,约束必须出现在类型说明符的后面。

  • 从泛型类中继承

    类可以从泛型中继承,如

class Farm<T> : IEnumerable<T> where T : Animal
{
}

如上代码Farm<T>是一个接口类型,同样对于T的约束也会在IEnumerable中使用的T上添加一个额外的约束,这可以用于限制用于约束的类型,但是需要遵守一些规则。

    首先,如果某个类型所继承的基类型中受到了约束,该类型就不能接触约束,即类型T在基类中使用时所受到的约束,必须扩展到子类中,至少于基类的约束相同。

  • 泛型运算符

    泛型类也支持运算符的重写。

  • 泛型结构

    结构与类相同,只是有一些细微的差别,而且结构是值类型,不是引用类型,所以可以创建泛型结构,如:

struct MyGenericStruct<T1, T2>
{
}

2.定义泛型接口

定义泛型接口于定义泛型类所用的技术相同,例如:

  interface IGeneric<T> where T : Object
    {
        void Sum(T x, T y);
    }

3.定义泛型方法

    可以使用泛型方法以达到泛型方法的更一般形式,在泛型方法中,参数类型或返回类型由泛型类型参数所决定。

,例如:

  T GetDefault<T>()
           {
               return default(T);
           }

可以使用非泛型类,实现泛型方法:

   public class Defaulter
    {
        public T GetDefault<T>()
        {
            return default(T);
        }
    }

 如果类是泛型的,那么需要为类中的泛型方法提供不同的标示符。如下代码会提示泛型方法:

  public class Defaulter<T>
    {
        public T GetDefault<T>()
        {
            return default(T);
        }
    }

会提示内部泛型参数与外部泛型参数相同,此时应该更改泛型标示符。

 

本篇内容参考C#入门经典。

c#高级编程笔记day5,9月13日(泛型)

【重点】泛型:有了泛型,就可以创建独立于被包含类型的类和方法了。我们不必给不同的类型编写功能相同的许多方法和类,只创建一个方法或类即可,以下是泛型的特点:性能、类型安全性、二进制代码重用、代码的扩展、... 查看详情

[unity]c#中级编程-04-泛型/构造函数/ref(代码片段)

[Unity中文课堂教程]C#中级编程-04-泛型/构造函数/ref原教程视频地址:《[Unity中文课堂教程预告片]C#中级编程_哔哩哔哩_bilibili》《C#中级编程-Unity中文课堂(u3d.cn)》《C#泛型(Generic)|菜鸟教程(runoob.com)》《C#泛型讲解_泛... 查看详情

c#泛型简介

摘要:本文讨论泛型处理的问题空间、它们的实现方式、该编程模型的好处,以及独特的创新(例如,约束、一般方法和委托以及一般继承)。此外,本文还讨论.NETFramework如何利用泛型。下载GenericsInCSharp.msi示例文件 。注&nb... 查看详情

C# 语言:泛型、打开/关闭、绑定/未绑定、构造

】C#语言:泛型、打开/关闭、绑定/未绑定、构造【英文标题】:C#Language:generics,open/closed,bound/unbound,constructed【发布时间】:2011-09-3005:24:36【问题描述】:我正在阅读AndersHejlsberg等人撰写的《C#编程语言》第4版。有几个定义有点... 查看详情

c#泛型的使用

01—泛型概述    泛型是用于处理算法、数据结构的一种编程方法。泛型的目标是采用广泛适用和可交互性的形式来表示算法和数据结构,以使它们能够直接用于软件构造。泛型类、结构、接口、委托和方法可以根据它们存... 查看详情

c#编程(五十)----------栈

...栈是后进先出.Stack与Stack<T>,像队列一样,栈也提供了泛型与非泛型版本.Stack的方法:方法说明Pop()从栈顶读栈并删除元素Push()存放数据,存在栈顶Peek()从栈顶读,但不删除 案例:using System;using System.Collections;using 查看详情

c#中的泛型

一、泛型的概念首先我们先来了解一下泛型的定义:泛型允许我们延迟编写类或方法中的编程元素的数据类型的规范,直到实际在程序中使用它的时候。(也就是说泛型是可以与任何数据类型一起工作的类或方法࿰... 查看详情

unity的c#学习——泛型的创建与继承泛型集合类泛型中的约束和反射(代码片段)

文章目录泛型1、泛型的名称由来2、泛型的创建与调用3、泛型类与非泛型类的继承4、泛型集合类5、泛型中约束与反射的应用5.1约束——限定可使用的数据类型5.2反射——获取要使用的数据类型泛型C#泛型是C#2.0中引入的一个非常... 查看详情

索引器(c#编程指南)

...它们的取值函数采用参数。在下面的示例中,定义了一个泛型类,并为其提供了简单的get和set取值函数方法(作为分配和检索值的方法)。Program类创建了此类的一个实例,用于存储字符串。C#classSampleCollection<T>{//Decl 查看详情

msdn搬运之[泛型-1]

泛型(C#编程指南)泛型是2.0版C#语言和公共语言运行库(CLR)中的一个新功能。泛型将类型参数的概念引入.NETFramework,类型参数使得设计如下类和方法成为可能:这些类和方法将一个或多个类型的指定推迟到客户端代码声明并实... 查看详情

c#进阶c#泛型(代码片段)

...18【C#进阶】C#事件19【C#进阶】C#集合类文章目录前言1、泛型的概念2、泛型的使用2.1、类型参数的命名2.2、泛型类2.3、泛型接口2.4、泛型方法2.5、泛型委托3、泛型参数的约束3.1、值类型约束3.2、引用类型约束4、泛型的特性总结... 查看详情

详解c#泛型(代码片段)

  一、前面两篇文章分别介绍了定义泛型类型、泛型委托、泛型接口以及声明泛型方法:  详解C#泛型(一)  详解C#泛型(二)  首先回顾下如何构建泛型类:publicclassMyClass<T>publicvoidMyFunc()//…  其中,尖括号<... 查看详情

记录c#泛型(代码片段)

常见的泛型类型泛型类classMyClass<T>//......泛型接口interfaceGenericInterface<T>voidGenericMethod(Tt);泛型方法publicvoidMyGenericMethod<T>()//......泛型数组publicT[]GenericArray;泛型委托publicdelegateTOu 查看详情

索引器(c#编程指南)

...于它们的访问器采用参数。在下面的示例中,定义了一个泛型类,并为其提供了简单的 get 和 set 访问器方法(作为分配和检索值的方法)。Progr 查看详情

理解c#泛型原理

前言 我们都知道泛型在C#的重要性,泛型是OOP语言中三大特征的多态的最重要的体现,几乎泛型撑起了整个.NET框架,在讲泛型之前,我们可以抛出一个问题,我们现在需要一个可扩容的数组类,且满足所有类型,不管是值类型... 查看详情

c#泛型

简介:  先看看泛型的概念--“通过参数化类型来实现在同一份代码上操作多种数据类型。利用“参数化类型”将类型抽象化,从而实现灵活的复用”。  很多初学者在刚开始接触泛型的时候会比较难理解“泛... 查看详情

详解c#泛型(代码片段)

  一、C#中的泛型引入了类型参数的概念,类似于C++中的模板,类型参数可以使类型或方法中的一个或多个类型的指定推迟到实例化或调用时,使用泛型可以更大程度的重用代码、保护类型安全性并提高性能;可以创建自定义... 查看详情

《c#零基础入门之百识百例》(八十一)泛型概念介绍--泛型类/结构/接口/委托

C#零基础入门泛型和系统类--泛型概念介绍--泛型类/结构/接口/委托前言一,泛型概念二,泛型类2.1声明泛型类2.2使用泛型类一,泛型结构三,泛型接口一,泛型接口声明二,泛型接口使用四,泛型委托4.1泛型委托声明4.2泛型委托... 查看详情