List<int>
和int list
之间有什么区别吗?
例如,当我写一个函数
let somefn a : int list = a
和
let somefn2 a : List<int> = a
返回值类型因符号样式而异,甚至在控制台输出中,当我调用这些函数时,它会显示两种明显的类型
val it : int list = ...
和
val it : List<int> = ...
虽然逻辑和想法似乎相同,但解释器/编译器以不同的方式解释这两种类型。
有什么不同吗?
答案 0 :(得分:17)
要稍微扩展John Palmer的正确答案,这里是一个F#互动会话,说明int list
和List<int>
是同义词的方式,直到它们不是。并注意如果还有list<int>
和ResizeArray<int>
的额外混淆:
F# Interactive for F# 4.0 (Open Source Edition)
Freely distributed under the Apache 2.0 Open Source License
For help type #help;;
> typeof<list<int>>.Namespace ;;
val it : string = "Microsoft.FSharp.Collections"
> typeof<list<int>>.Name ;;
val it : string = "FSharpList`1"
> typeof<List<int>>.Namespace ;;
val it : string = "Microsoft.FSharp.Collections"
> typeof<List<int>>.Name ;;
val it : string = "FSharpList`1"
> typeof<int list>.Namespace ;;
val it : string = "Microsoft.FSharp.Collections"
> typeof<int list>.Name ;;
val it : string = "FSharpList`1"
> typeof<ResizeArray<int>>.Namespace ;;
val it : string = "System.Collections.Generic"
> typeof<ResizeArray<int>>.Name ;;
val it : string = "List`1"
-
- printfn "Now we'll open System.Collections.Generic. Watch what happens."
- ;;
Now we'll open System.Collections.Generic. Watch what happens.
val it : unit = ()
> open System.Collections.Generic ;;
> typeof<list<int>>.Namespace ;;
val it : string = "Microsoft.FSharp.Collections"
> typeof<list<int>>.Name ;;
val it : string = "FSharpList`1"
> typeof<List<int>>.Namespace ;;
val it : string = "System.Collections.Generic"
> typeof<List<int>>.Name ;;
val it : string = "List`1"
> typeof<int list>.Namespace ;;
val it : string = "Microsoft.FSharp.Collections"
> typeof<int list>.Name ;;
val it : string = "FSharpList`1"
> typeof<ResizeArray<int>>.Namespace ;;
val it : string = "System.Collections.Generic"
> typeof<ResizeArray<int>>.Name ;;
val it : string = "List`1"
所以带有大写L的List<int>
将是F#列表类型(带有头指针的不可变链表,其具有O(1)头访问和前置,但O(N)尾访问和追加)如果您尚未打开System.Collections.Generic
命名空间。但是,如果你拥有,那么突然List<int>
解析为.Net System.Collections.Generic.List<T>
类,这是一个带有O(1)查找的可变数据结构在任何地方,摊销O(1)追加,但O(N)预先。所以它真的很重要你正在使用哪一个。
为了安全起见,如果您打算使用F#列表结构,我会将其写为int list
(我的偏好,因为它读起来像英语)或list<int>
(其中一些)人们更喜欢,因为它读起来像C#)。当你打开.Net命名空间时,这些都不会突然获得不同的含义;他们将继续参考F#列表结构。并避免使用List<int>
来引用F#列表;只有在打开System.Collections.Generic
命名空间并且打算获得.Net System.Collections.Generic.List<T>
实例时才使用它。最后请注意,在F#中,System.Collections.Generic.List<T>
有一个类型别名,而不会打开System.Collections.Generic
命名空间。默认情况下,无需打开任何名称空间,您可以使用名称ResizeArray<T>
。
要点:
安全类型名称:
int list
和list<int>
(始终引用F#单链接列表类型)ResizeArray<int>
(始终指C#System.Collections.Generic.List<T>
类型)不安全的类型名称,因为它们的含义会根据您打开的名称空间而改变:
List<int>
(首先是指F#单链接列表类型,但如果打开System.Collections.Generic
命名空间,会将更改为C#类型)。作为一般规则,请勿使用此类型名称;如果您想在F#中使用此类型,请改用ResizeArray<int>
。答案 1 :(得分:8)
没有区别,有一个类型别名。
除了一个案例,你已经在哪里运行
open System.Collections.Generic
哪个有自己的列表类型
答案 2 :(得分:3)
通常,对于包含一个参数的通用类型,TypeParameter GenericType
相当于GenericType<TypeParameter>
。
FSharp.Core中声明的F#immutable列表类型在范围内,默认情况下有两个名称:List
和list
。它有一个类型参数,因此int list
,list<int>
,int List
和List<int>
是等效的。
System.Collections.Generic
有一个不同的List<'T>
类型,它在F#中具有更合适的别名ResizeArray
。如果您打开System.Collections.Generic
,List
会引用此可变的数组换行类型。
为避免混淆,习惯上不使用List
使用大写L
来引用F#中的类型。相反,list
使用小写l
用于FP源,不可变,单链接列表,而ResizeArray
用于引用OO样式的可变集合。大多数人还坚持使用不同的样式int list
与ResizeArray<int>
,并避免使用其他组合。
对于类型信息,IDE和类似信息有时会尝试以声明方式显示类型,因为通常有很多方法可以引用相同的类型。这并不意味着行为上的差异。