Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 为什么不总是使用泛型?_.net_Generics - Fatal编程技术网

.net 为什么不总是使用泛型?

.net 为什么不总是使用泛型?,.net,generics,.net,Generics,我正在读SO关于泛型的现有帖子。如果泛型有很多优点,比如类型安全,没有装箱/拆箱的开销,而且速度很快,为什么不总是使用它呢?为什么要使用非泛型对象呢 已编辑(问题在下面进一步扩展) 我有点困惑。上一次我在几个月前读到关于泛型的文章时,我读到如果参数中的类型是可变的,那么应该使用泛型来防止错误。不过,我现在看到的是泛型将实现限制为固定类型,而非泛型对象允许您在运行时定义参数类型 请帮我看看我遗漏了什么 其次,在适当的OOP设计(泛型等)中使用这些类型的构造在您在团队中工作并且代码可共享时非常有用。

我正在读SO关于泛型的现有帖子。如果泛型有很多优点,比如类型安全,没有装箱/拆箱的开销,而且速度很快,为什么不总是使用它呢?为什么要使用非泛型对象呢

已编辑(问题在下面进一步扩展)

我有点困惑。上一次我在几个月前读到关于泛型的文章时,我读到如果参数中的类型是可变的,那么应该使用泛型来防止错误。不过,我现在看到的是泛型将实现限制为固定类型,而非泛型对象允许您在运行时定义参数类型

请帮我看看我遗漏了什么


其次,在适当的OOP设计(泛型等)中使用这些类型的构造在您在团队中工作并且代码可共享时非常有用。对于一个规模较小的程序员来说,谁知道参数中必须包含什么类型,似乎没有必要担心,使用泛型类型和非泛型类型之间也没有什么区别。这是准确的吗?

通常您应该-但是,有时(特别是在编写库代码时)不可能(或者肯定不方便)了解调用类型(甚至在
T
方面),因此非泛型类型(主要是
IList
IEnumerable
)非常有用。数据绑定就是一个很好的例子。事实上,使用泛型通常会使涉及反射的任何内容变得更加困难,而且由于(通过反射的性质)您已经失去了这些好处,您也可以直接使用非泛型代码。反射和泛型根本不是很好的朋友。

泛型可能快速且类型安全,但也增加了复杂性(另一个方面可能会有所不同,程序员必须理解)。谁将维护您的代码?不是所有的泛型技巧(或lambdas,或依赖注入,或…)都值得。想想你将要解决什么问题,以及这个问题的哪些部分将来可能会改变。为这些案例设计。最灵活的软件太复杂,普通程序员无法维护

有时“对象”集合是不可避免的。当同一控件/集合中有多个类型时,通常会发生这种情况-它们唯一的共同类型是“object”,因此这是集合的最佳类型

使用PropertyGrid可以看到不时弹出的对象(与集合无关)的另一种情况。第三方属性网格可能允许您附加一个“验证器”,该验证器返回用户对网格上给定属性的新值是否可接受。由于PropertyGrid不知道它将显示哪些属性,因此它能给验证器的最好结果就是一个对象——即使验证器确切地知道它将被调用的类型


但根据Mark的回答,.NET中的大多数(全部?)非泛型集合只是出于遗留原因而存在的。如果今天重新制作.NET,您可以肯定标准库将看起来非常不同。

泛型是通常的做法。增加的复杂性可能是反对它的一个理由,但在大多数情况下,它的好处是完全值得考虑的。作为一般的经验法则,接受它。反射是另一种情况,泛型使之更难。但只有在没有意义的情况下,我才避免使用泛型

我喜欢避免泛型的一个场景是使方法泛型化,因为它不符合泛型的预期目的,并且可能会产生误导引入泛型是为了更好的类型安全性和性能(当涉及值类型时)。若两者都不起作用,那个么通用方法可能会误导开发人员。例如,考虑从

通过查看方法定义,人们会倾向于认为这种方法没有拳击惩罚,但让调用方清楚地知道这是一种好方法。我喜欢这样:

public void DoSomething(object request) //boxes here
{
    var type = request.GetType(); 

    //or other reflection calls which involves boxing
}
除此之外,我一直更喜欢泛型


使用
dynamic
时,两者可能会有不同的行为

public void Generic<T>(T request)
{
}

public void Object(object request)
{
}

dynamic d = null;
Object(d); //no issues
Generic(d); //run-time explosion; can not infer type argument
public-void-Generic(T请求)
{
}
公共无效对象(对象请求)
{
}
动态d=null;
目标(d)//没问题
一般(d)//运行时爆炸;无法推断类型参数

不是一个需要考虑的因素,只是一个值得考虑的行为上的愚蠢差异。

泛型使代码更可重用,增加类型安全性。如果你看到任何好的API(JDK,Scala等),你到处都会看到泛型。 泛型最大的挑战是,要适应它有点棘手,因此许多程序员发现泛型代码不可读


但是在这里,我们应该解决真正的问题(弥合知识鸿沟),而不是避免泛型。

一些有效的一般观点,但我不确定我能看到泛型如何在这里增加了很多复杂性。。。事实上,在很多方面,泛型更难出错(编译器会对你发牢骚)。马克,你的上下文并不十分清楚。添加设计元素总是会增加复杂性。例如,另一个间接层本身并不会增加很多复杂性,但所有这些都会增加。问题在于增加的元素是否值得。编写代码时出错是一回事:理解必须维护的代码是另一回事。如果您有一个业务层订单类,在什么情况下您会使其成为通用的?什么参数?不幸的是,答案是:视情况而定+回答得很好。编码时最重要的考虑因素之一是,某种设计的好处是否大于增加复杂性的成本。@马克:我长期以来的疑虑已经消除。很高兴知道非泛型的东西只用于遗留原因。@RPK:事实上,非泛型的东西还有其他一些优点。例如,如果类超级集合实现了IList,但也实现了只读非g
public void DoSomething<T>(T request)
{
    var type = request.GetType(); //boxed already in case of value types.

    //or other reflection calls which involves boxing
}
public void DoSomething(object request) //boxes here
{
    var type = request.GetType(); 

    //or other reflection calls which involves boxing
}
public void Generic<T>(T request)
{
}

public void Object(object request)
{
}

dynamic d = null;
Object(d); //no issues
Generic(d); //run-time explosion; can not infer type argument