有人可以澄清何时使用typedefof<'T>与typeof<'T>?
typedefof<System.String>
和typeof<System.String>
都会返回相同的Type
个实例。
但是,它们会为System.Collections.Generic.List<_>
返回不同的实例和不同的信息。
我可以将typedefof
视为新的typeof
吗?我应该切换到始终使用typedefof
吗?还是比它更微妙?
答案 0 :(得分:8)
这应该说明不同之处。使用typeof
时,编译器会推断类型参数并构造具体类型。在这种情况下,推断的类型参数是System.Object
:
let t1 = typeof<System.Collections.Generic.List<_>>
let t2 = typedefof<System.Collections.Generic.List<_>>
printfn "t1 is %s" t1.FullName
printfn "t2 is %s" t2.FullName
输出:
t1 is System.Collections.Generic.List`1[[System.Object, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]
t2 is System.Collections.Generic.List`1
因为typeof
只能返回构造的类型,所以如果你需要一个表示泛型类型定义的类型对象,则需要typedefof
。
答案 1 :(得分:7)
typeof
对象时,将使用 System.Type
。如果要获取表示泛型类型的类型定义的typedefof
,则使用System.Type
。作为使用两者的示例,假设您有一个名为Generic<'a>
的类型,并且您想要创建一个函数,该函数返回任何给定类型的System.Type
的{{1}}对象。
Generic
在这里,您可以使用type Generic<'a> = Value of 'a
let makeGenericOf<'a> () =
typedefof<Generic<_>>.MakeGenericType(typeof<'a>)
函数来获取类型定义,并typedefof
使用typeof
来构建通用'a
Generic<'a>
}。
答案 2 :(得分:1)
我非常感谢phoog,Aaron和JLRishe的回答。以下是我根据他们的答案和我自己的实验所学到的知识。
有两个Type
个实例与泛型相关联。
与通用关联的Type
具有特定的类型参数。例如,Type
与List<int>
相关联,Type
与List<string>
相关联。这是您使用typeof<>
时获得的。
> typeof<List<string>>.ToString();;
val it : string = "Microsoft.FSharp.Collections.FSharpList`1[System.String]"
> typeof<List<int>>.ToString();;
val it : string = "Microsoft.FSharp.Collections.FSharpList`1[System.Int32]"
有一个Type
与泛型类型定义本身相关联。例如,与Type
关联的单个List<'T>
与List<int>
,List<string>
和List<_>
相同。这是您使用typedefof<>
时获得的。
> typedefof<List<string>>.ToString();;
val it : string = "Microsoft.FSharp.Collections.FSharpList`1[T]"
> typedefof<List<int>>.ToString();;
val it : string = "Microsoft.FSharp.Collections.FSharpList`1[T]"
> typedefof<List<_>>.ToString();;
val it : string = "Microsoft.FSharp.Collections.FSharpList`1[T]"
顺便说一句,Type
类有GetGenericTypeDefinition()
的实例方法。这意味着,以下两个返回相同的实例:
> Object.ReferenceEquals(typeof<List<int>>.GetGenericTypeDefinition(), typedefof<List<int>>);;
val it : bool = true
如果致电typeof<List<_>>
会怎样?如phoog所述,您可以获得Type
List<Object>
的定义。
> typeof<List<_>>.ToString();;
val it : string = "Microsoft.FSharp.Collections.FSharpList`1[System.Object]"
这有助于理解。例如,假设我需要知道对象是否是通用列表(任何类型)。
// does not give me the answer I naively expected
> o.GetType() = typeof<List<_>>;;
val it : bool = false
// does this reference point to a List<'T>?
> o.GetType().IsGenericType && o.GetType().GetGenericTypeDefinition() = typedefof<List<_>>;;
val it : bool = true
此外,如果您想要后期实例化泛型类型,可以使用Aaron提到的MakeGenericType(...)
方法。
> let myList = typedefof<List<_>>.MakeGenericType(typeof<int>);;
val myList : Type = Microsoft.FSharp.Collections.FSharpList`1[System.Int32]