Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/287.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
混淆C#duck类型、隐式转换和不一致_C#_Design Decisions - Fatal编程技术网

混淆C#duck类型、隐式转换和不一致

混淆C#duck类型、隐式转换和不一致,c#,design-decisions,C#,Design Decisions,每个人似乎都喜欢鸭子打字,如果它看起来像鸭子,表现得像鸭子,就要像鸭子一样对待它。C#4.0允许duck类型,current在一些情况下支持它(请参阅中的“C#已经使用duck类型很长时间了”) 现在。。。几乎所有东西都有一个.AnotherType()。我无法理解int需要.ToString(),但当将列表传递到需要obj[]的函数时,它真的需要.ToArray()吗?。这似乎前后矛盾 有人能解释这些不一致的地方,解释原因吗?为了让我理解(或任何其他设计决策)或给我任何类型的见解吗?几乎所有的

每个人似乎都喜欢鸭子打字,如果它看起来像鸭子,表现得像鸭子,就要像鸭子一样对待它。C#4.0允许duck类型,current在一些情况下支持它(请参阅中的“C#已经使用duck类型很长时间了”)

现在。。。几乎所有东西都有一个.AnotherType()。我无法理解int需要.ToString(),但当将列表传递到需要obj[]的函数时,它真的需要.ToArray()吗?。这似乎前后矛盾


有人能解释这些不一致的地方,解释原因吗?为了让我理解(或任何其他设计决策)或给我任何类型的见解吗?

几乎所有的收藏都应该提供一种方法,允许从其他普通收藏中创建它,或者允许它被制作成(或更好地像其他普通收藏一样处理)

数组功能强大,但推理起来很复杂,因为它们(本质上)是可变的,但允许在需要时进行一些强大的优化(例如,高效的快速排序实现确实需要能够就地交换元素)。
序列(
IEnumerable
对您来说)非常优秀,因为它们对自身的要求太少(包括至关重要的修改它们的方式),这意味着期望它们的代码往往非常灵活且广泛有用

能够简单而容易地从另一个集合中获取特定种类的集合,允许您编写代码来处理它所需的结构,但可以通过简单的转换调用轻松地与许多其他种类的结构交互。如果后来发现这是一个性能问题,那么您可能必须避免转换,并让更多的代码库了解底层类型,但首先可以干净快速地编写代码

已经存在许多api,它们期望某种类型的集合,可能的原因包括:

  • 在2.0更改之前编写,该更改使.Net中的集合更加丰富
  • 因为他们知道他们需要改变状态,所以他们让调用者负责提供 要更改的状态(如就地排序函数)
  • 他们写得很差
值得注意的是,在.NET2.0之前的版本中,除了数组之外,没有任何类型的强类型集合,这意味着事后来看,许多BCLAPI的设计都很糟糕。BCL中的反射api是一个值得注意的例子,当数组应该是IEnumerable时,它会到处返回数组

因此,能够轻松地从一种显式集合转换到另一种集合在现实世界中非常有用

重新阅读您的声明(目前这不是一个真正的问题),您似乎对从一个集合转换到另一个集合时是否需要显式转换/转换方法感到困惑

答案是,这要看情况而定(动态确实在某种程度上改变了一些事情,但改变不了多少)

简单地说,如果可以像预期的类型一样透明地处理集合实例,则不需要进行转换。一般来说,函数应该尽量少地请求(通常情况下是IEnumerable),然后传入的任何实际类型都会通过多态性正常工作。在某些情况下,运行时必须采取一些措施来实现这一点(数组就是一个值得注意的例子),但通常情况下这是很好的

事情变得复杂的地方是函数需要具体类型的地方。同样糟糕的前期设计,比如在添加HashSet时没有包含ISet接口,这意味着如果您有一个方法确实需要一个集合,那么您必须使用一个具体的类型或滚动您自己的ISet和支持集,这是不愉快的。某些转换操作(例如从集合到列表)在只读上下文中是可行的(您只需确定地枚举集合中的所有值),但在写入上下文中是不可行的(例如,您可以向列表中添加两次内容,但不能向集合中添加)

这就是关于几乎所有事物都是不可变的通用功能约定的帮助,通过这样做,就更容易不太关心集合的具体实现,而只考虑它的外部可见行为(一个集合或哈希表的红色balck树——对消费者来说,它只是一个集合并不重要)


动态使事情变得有些复杂,因为要保持它的实现的“公理”是,当使用动态时,您应该得到与静态类型相同的结果,它必须处理诸如数组上的运行时魔法之类的情况。

几乎任何集合都应该提供一种方法,允许从其他常见集合创建它,或者允许将它制作成(或者更好地像这样处理)其他常见收藏

数组功能强大,但推理起来很复杂,因为它们(本质上)是可变的,但允许在需要时进行一些强大的优化(例如,高效的快速排序实现确实需要能够就地交换元素)。
序列(
IEnumerable
对您来说)非常优秀,因为它们对自身的要求太少(包括至关重要的修改它们的方式),这意味着期望它们的代码往往非常灵活且广泛有用

能够简单方便地从另一个集合中获取特定种类的集合,允许您编写代码来处理它所需的结构,但可以通过简单的转换调用轻松地与许多其他种类的结构进行交互。如果这后来成为性能问题,您可能必须避免转换,并充分利用代码库知道底层类型,但首先可以干净快速地编写它

已经存在许多api,它们期望某种类型的集合,可能的原因包括:

  • 在2.0更改之前编写,该更改使.Net中的集合更加丰富
  • 因为他们知道他们需要改变状态,所以他们让调用者负责提供 这个