首页 / 知识
关于c#:泛型有什么优点,为什么要使用泛型?
2023-04-16 06:03:00

What is cool about generics, why use them?我想我会把这个垒球提供给任何想从公园里踢出去的人。 什么是泛型,泛型的优点是什么,为什么,在哪里,应该如何使用它们? 请保持基本。 谢谢。
我真的很讨厌重复自己。我讨厌经常输入相同的东西。我不喜欢在有些许差异的情况下多次重述。 而不是创建:
我可以建立一个可重用的类...(如果您出于某种原因不想使用原始集合)
现在,我的效率提高了3倍,并且只需要维护一份副本即可。为什么您不想维护更少的代码?
对于必须与其他类进行交互的非收集类(例如 我不。
无需类型转换是Java泛型的最大优点之一,因为它将在编译时执行类型检查。这将减少在运行时抛出 好。 但是我怀疑您完全意识到这一点。 好。
起初,我也没有看到泛型的好处。我从1.4语法开始学习Java(即使当时还没有Java 5),当我遇到泛型时,我觉得要编写的代码更多,而且我真的不明白这样做的好处。 好。 现代IDE使使用泛型编写代码更加容易。 好。 大多数现代的,体面的IDE都足够聪明,可以协助使用泛型编写代码,尤其是代码完成。 好。
这是用 好。
确实,要创建一个新的 好。
好。
的确,我确实需要从候选列表中选择 好。 另外,由于类型是已知的,因此从通用集合中检索元素时,IDE会像该对象已经是其声明类型的对象一样起作用-无需强制IDE强制转换即可知道该对象的类型是。 好。
泛型的主要优势来自其与Java 5新功能的良好配合方式。这是将整数扔进 好。
在这段代码中,提供了三个Java 5新功能: 好。 好。 首先,原语的泛型和自动装箱允许以下几行: 好。
整数 好。 接下来,for-each循环将所有这三个条件都采用: 好。
首先,在每个循环中使用包含 好。 泛型可以是将Java 5中引入的新功能结合在一起的粘合剂,它只是使编码更简单,更安全。而且大多数时候,IDE足够聪明,可以为您提供良好的建议,因此,通常来说,键入的内容不会太多。 好。
坦率地说,从 好。 编辑-没有泛型的示例 好。
下面是上述 好。
(注意:以上代码将在编译时生成未经检查的转换警告。) 好。
使用非泛型集合时,输入到集合中的类型是类型为 好。
在上述各行中,自动装箱正在起作用-将原始 好。
这是至关重要的部分。 for-each循环起作用的原因是因为 好。
但是,由于没有类型信息,因此 好。
现在,从 好。
在此,从 好。
现在,将 好。 我希望我能举例说明Java 5的新功能可以与非泛型代码一起使用,但是它不像使用泛型编写代码那样简洁明了。而且,我认为,要充分利用Java 5的新功能,应该研究泛型,至少要允许进行编译时检查,以防止无效的类型转换在运行时引发异常。 好。 好。
如果要在1.5版本发布之前搜索Java错误数据库,则发现 对我而言,泛型的巨大优势在于它们可以在代码中记录重要的类型信息。如果我不希望将类型信息记录在代码中,那么我将使用动态类型的语言,或者至少使用具有更多隐式类型推断的语言。 保持对象的集合本身不是坏样式(但是,常见的样式是有效地忽略封装)。而是取决于您在做什么。将泛型传递给"算法"稍微容易一点(在编译时或编译时)。
Java中的泛型促进了参数多态性。通过类型参数,可以将参数传递给类型。就像 这是我每天使用的泛型类型的几个示例。首先,一个非常有用的通用接口:
该接口表示,对于
在泛型之前,通过使用
这比使用继承要灵活得多,因为我们可以坚持使用合成和参数多态的主题,而不必锁定脆弱的层次结构。 Java的泛型并不是完美的。例如,您可以抽象类型,但是不能抽象类型构造函数。也就是说,您可以说"对于任何类型T",但不能说"对于任何采用类型参数A的类型T"。 我在这里写了一篇关于Java泛型的限制的文章。 泛型的一个巨大胜利就是它们可以避免子类化。子类化往往会导致脆弱的类层次结构难以扩展,并且难以在不查看整个层次结构的情况下单独理解类。
在泛型之前,您可能需要将 泛型避免了装箱和拆箱对性能的影响。基本上,请看ArrayList vs List < T >。两者都具有相同的核心功能,但是List < T >会快很多,因为您不必对对象进行装箱。 泛型的最大好处是代码重用。假设您有很多业务对象,并且您将为每个实体编写非常相似的代码以执行相同的操作。 (即Linq to SQL操作)。 使用泛型,您可以创建一个类,该类将能够给定从给定基类继承的任何类型的给定类型,或者实现给定接口,例如:
请注意,在上面的DoSomething方法中,如果类型不同,则同一服务的重用。真正的优雅! 在您的工作中使用泛型还有很多其他重要的原因,这是我的最爱。 我喜欢它们是因为它们为您提供了一种定义自定义类型的快速方法(无论如何,我还是会使用它们)。 因此,例如,不必定义由字符串和整数组成的结构,然后必须实现关于如何访问这些结构的数组的整套对象和方法,等等,您只需制作一个Dictionary
而编译器/ IDE会完成其余的繁重工作。特别是使用"字典",您可以将第一种类型用作键(无重复值)。 举一个很好的例子。假设您有一个名为Foo的课程
例子1
在上面的代码中,如果我尝试添加FireTruck类而不是Foo,则ArrayList将添加它,但是Foo的通用列表将导致引发异常。 例子二。 现在,您有两个数组列表,并且要在每个列表上调用Bar()函数。由于ArrayList充满了对象,因此必须先强制??转换它们才能调用bar。但是由于Foo的通用列表只能包含Foos,因此您可以直接在它们上调用Bar()。
本质上,您在检查仅应存在的条件,因为接口是以对象表示的。 我对仿制药的最初反应与您的相似-"太混乱了,太复杂了"。我的经验是,使用它们一段时间后,您会习惯它们,没有它们的代码感觉不太清晰,也不太舒服。除此之外,java世界的其余部分都使用它们,因此您最终将不得不使用该程序,对吗? 您是否从未编写过方法(或类),其中方法/类的关键概念未紧密绑定到参数/实例变量的特定数据类型(请考虑链接列表,max / min函数,二进制搜索)等)。
您是否从未希望过可以重用算法/代码而不必求助于n-paste重用或损害强类型(例如,我希望使用 这就是为什么您应该使用泛型(或更好的东西)的原因。 不要忘记,泛型不仅被类使用,它们也可以被方法使用。例如,采用以下代码段:
它很简单,但是可以非常优雅地使用。令人高兴的是,该方法返回的结果与给定的一样。当您处理需要重新抛出给调用者的异常时,这将有所帮助:
关键是,您不会通过将其传递给方法来丢失该类型。您可以抛出正确的异常类型,而不仅仅是 这只是通用方法的一种简单使用示例。泛型方法还可以做很多其他的事情。在我看来,最酷的是使用泛型进行类型推断。请看以下示例(摘自Josh Bloch的Effective Java 2nd Edition):
这并不能解决很多问题,但是当泛型类型很长(或嵌套;即 正如Mitchel指出的那样,主要优点是无需定义多个类即可进行强类型化。 这样,您可以执行以下操作:
如果没有泛型,则必须将blah [0]强制转换为正确的类型才能访问其功能。 无论如何,jvm强制转换...它隐式创建将通用类型视为"对象"的代码,并创建对所需实例化的强制转换。 Java泛型只是语法糖。 我知道这是一个C#问题,但是泛型也用在其他语言中,并且它们的用途/目标非常相似。 Java集合从Java 1.5开始使用泛型。因此,使用它们的一个好地方是在创建自己的类似集合的对象时。 我几乎在每个地方都可以看到一个示例,Pair类具有两个对象,但是需要以通用方式处理这些对象。
每当使用此Pair类时,您都可以指定要处理的对象类型,并且任何类型转换问题都将在编译时而不是运行时显示。 泛型也可以使用关键字" super"和" extends"来定义范围。例如,如果要处理通用类型,但要确保它扩展了名为Foo的类(它具有setTitle方法):
尽管它本身并不是很有趣,但是知道每当您使用FooManager时,您都知道它将处理MyClass类型,并且MyClass扩展了Foo,这很有用。 从Sun Java文档中,响应"我为什么要使用泛型?": "泛型为您提供了一种向编译器传达集合类型的方法,以便可以对其进行检查。一旦编译器知道集合的元素类型,编译器便可以检查您是否一致地使用了集合并可以插入对从集合中取出的值进行正确的强制转换...使用泛型的代码更清晰,更安全....编译器可以在编译时验证在运行时不违反类型约束[强调我的]。程序编译时没有警告,我们可以肯定地说它不会在运行时引发ClassCastException。使用泛型的最终效果是提高可读性和鲁棒性,尤其是在大型程序中。 泛型允许您创建强类型化的对象,但不必定义特定类型。我认为最有用的示例是List和类似的类。 使用通用列表,您可以随心所欲地拥有一个列表列表,并且您始终可以引用强类型,而不必进行转换或类似数组或标准列表的操作。 要添加/扩展的几件事(从.NET角度而言): 泛型类型使您可以创建基于角色的类和接口。这已经用更基本的术语说过了,但是我发现您开始使用以与类型无关的方式实现的类来设计代码-这导致了高度可重用的代码。 方法的通用论点可以做同样的事情,但是它们也有助于将"告诉不问"原理应用于转换,即"给我我想要的,如果不能,请告诉我原因"。 总之,泛型使您可以更精确地指定要执行的操作(更强的键入)。 这对您有几个好处:
最主要的原因是它们提供了类型安全性
相对于
作为一个简单的例子。 使用泛型(尤其是集合/列表)的另一个优点是您可以获得编译时类型检查。当使用通用列表而不是对象列表时,这真的很有用。 已经提到了诸如"类型安全"和"无强制转换"之类的明显好处,因此也许我可以谈谈其他一些"好处",希望对它有帮助。 首先,泛型是一个与语言无关的概念,而IMO,如果您同时考虑常规(运行时)多态性,则可能更有意义。 例如,我们从面向对象设计中了解到的多态性具有运行时概念,即在调用者对象随程序执行时在运行时确定,并根据运行时类型相应地调用相关方法。在泛型中,这个想法有些相似,但是所有事情都是在编译时发生的。这是什么意思,以及您如何利用它? (让我们坚持使用通用方法来保持紧凑)这意味着您仍然可以在单独的类上使用相同的方法(就像您以前在多态类中所做的一样),但是这次它们由编译器自动生成,取决于设置的类型在编译时。您可以根据编译时给出的类型对方法进行参数化。因此,不必像在运行时多态性(方法重写)中那样为每种类型从头开始编写方法,而应让编译器在编译期间完成工作。这具有明显的优势,因为您无需推断系统中可能使用的所有可能的类型,这无需更改代码即可使其具有更高的可伸缩性。 类的工作方式几乎相同。您对类型进行参数化,并且代码由编译器生成。 一旦有了"编译时间"的概念,就可以使用"有界"类型,并限制可以通过类/方法作为参数化类型传递的内容。因此,您可以控制要传递的内容是有力的,尤其是您的框架正在被其他人使用。
现在没有人可以设置MyObject以外的其他功能。 另外,您可以在方法参数上"强制"类型约束,这意味着可以确保两个方法参数都依赖于同一类型。
希望所有这些都有意义。 我在使用SpringORM和Hibernate实现的GenericDao中使用了它们,例如
通过使用泛型,我对该DAO的实现迫使开发人员仅通过将GenericDao子类化而将它们仅为其设计的实体传递给他们。
我的小框架更加健壮(具有过滤,延迟加载,搜索之类的功能)。我只是在这里简化了一个例子 我像史蒂夫和您一样,在一开始就说"太凌乱和复杂",但现在我看到了它的优势 如果您的集合包含值类型,则在将它们插入到集合中时不需要对对象进行装箱/拆箱操作,因此您的性能会大大提高。诸如resharper之类的很酷的插件可以为您生成更多代码,例如foreach循环。 泛型使您可以对应该包含任何对象的对象和数据结构使用强类型。从通用结构(装箱/拆箱)中检索对象时,它还消除了繁琐而昂贵的类型转换。 一个同时使用两者的示例是一个链表。如果只能使用对象Foo,则链表类有什么好处?要实现可处理任何类型对象的链表,如果您希望链表仅包含一种类型的对象,则链表和假设节点内部类中的节点必须是通用的。 使用泛型进行收集既简单又干净。即使您在其他任何地方都花钱,从收藏中获得的收益对我来说也是一个胜利。
与
要么
仅凭这一点就值得泛型的边际"成本",而且您不必成为泛型大师就可以使用它并获得价值。 泛型还使您能够创建更多可重用的对象/方法,同时仍提供特定于类型的支持。在某些情况下,您还会获得很多性能。我不了解Java泛型的完整规范,但是在.NET中,我可以在Type参数上指定约束,例如,实现接口,构造函数和派生。 我曾经就这个话题发表过演讲。您可以在http://www.adventuresinsoftware.com/generics/上找到我的幻灯片,代码和音频记录。 |
最新内容
相关内容
字符串查找命令linux?
字符串查找命令linux?,系统,字符串,工具,信息,文件,命令,字符,选项,文本,范本,如何在Linux下查找文件内容包含某个特定字符串的文件在linux中glinux命令替换字符串?
linux命令替换字符串?,字符串,文件,批量,首次,数据,命令,内容,方法,用字,结尾,linux下批量查询文件内容字符串并替换一)通过vi编辑器来替换。vilinux拼接字符串命令?
linux拼接字符串命令?,系统,工作,代码,工具,名称,信息,地址,时间,数据,命令,linux中用shell时奇怪的字符串拼接和时间计算问题如果想要在变量linux使用命令的方法?
linux使用命令的方法?,系统,信息,工具,标准,数据,命令,左下角,目录,文件夹,图标,linux的cd命令的使用方法1、cd ~:回到用户家目录。注:这得看你添加字符串命令linux?
添加字符串命令linux?,情况,名称,文件,位置,名字,地方,连续,信息,命令,内容,Linux下怎么输入连字符?末尾加个\这个符号就能两行。部分命令也linux命令查找字符串?
linux命令查找字符串?,工具,信息,命令,字符串,系统,工作,文件,范本,样式,文本,Linux中使用grep命令,查询多个字符串Linux grep命令用于查找文linux命令输入方法?
linux命令输入方法?,系统,电脑,密码,管理,地址,命令,网站,工具,首开,位置,linux终端输入~怎么弄中间在电脑上打开需要的Word文件进入。进入到文linux命令字符串匹配?
linux命令字符串匹配?,系统,工具,命令,字符串,灵活,状态,文件,文本,模式,管道,图文说明Linux下grep查找含有某字符串的方法在linux中grep命令Python中什么是反射?使用方法有哪
Python中什么是反射?使用方法有哪些?,信息,培训,状态,术语,检测,反射,属性,对象,字符串,方法,反射这个术语在很多语言中都存在,并且存在大量的python字符串截取?
python字符串截取?,代码,步长,位置,分析,字符串,字符,信息,灵活,数字,表示,在Python中,字符串是一种非常常见的数据类型,它可以用来表示文本、数Python中有哪些方法可以解压文件?
Python中有哪些方法可以解压文件?,工具,系统,工作,培训,文件,文件夹,方法,窗体,不同于,以下内容,在Python学习和日常使用中,很容易造成文件过大Python列表类型list合并有哪些方法
Python列表类型list合并有哪些方法?,培训,方法,列表,可能会,数组,切片,下文,字符串,数据类型,请看,在Python编程语言中,有各种数据类型,比如字符