有人可以澄清何时使用typedefof <'T>与typeof <'T>?
双方typedefof<System.String>并typeof<System.String>返回相同的Type实例.
但是,它们返回不同的实例和不同的信息System.Collections.Generic.List<_>.
我能想到typedefof一个新的和改进的typeof吗?我应该切换到始终使用typedefof?还是比它更微妙?
Aar*_*ach 11
typeof当您想要获取System.Type给定类型的对象时使用. typedefof当您想要获取System.Type表示泛型类型的类型定义时使用.作为使用两者的示例,假设您有一个名为的类型Generic<'a>,并且您想要创建一个函数,该函数返回任何给定类型的System.Type对象Generic.
type Generic<'a> = Value of 'a
let makeGenericOf<'a> () =
typedefof<Generic<_>>.MakeGenericType(typeof<'a>)
Run Code Online (Sandbox Code Playgroud)
在这里,您将使用该typedefof函数来获取类型定义,并typeof获取'a用于构造泛型的类型Generic<'a> Type.
这应该说明不同之处.使用时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
Run Code Online (Sandbox Code Playgroud)
输出:
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
Run Code Online (Sandbox Code Playgroud)
因为typeof只能返回构造类型,typedefof所以如果需要表示泛型类型定义的类型对象,则必须这样做.
我非常感谢 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]"
Run Code Online (Sandbox Code Playgroud)有一个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]"
Run Code Online (Sandbox Code Playgroud)顺便说一句,该类Type有一个实例方法GetGenericTypeDefinition()。这意味着,以下两个返回相同的实例:
> Object.ReferenceEquals(typeof<List<int>>.GetGenericTypeDefinition(), typedefof<List<int>>);;
val it : bool = true
Run Code Online (Sandbox Code Playgroud)
如果你打电话会发生什么typeof<List<_>>?正如 phoog 提到的,您将得到 的Type定义。List<Object>
> typeof<List<_>>.ToString();;
val it : string = "Microsoft.FSharp.Collections.FSharpList`1[System.Object]"
Run Code Online (Sandbox Code Playgroud)
这一切都有助于理解。例如,假设我需要知道一个对象是否是通用列表(任何类型)。
// 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
Run Code Online (Sandbox Code Playgroud)
另外,如果你想后期绑定实例化泛型类型,你可以使用MakeGenericType(...)Aaron 提到的方法。
> let myList = typedefof<List<_>>.MakeGenericType(typeof<int>);;
val myList : Type = Microsoft.FSharp.Collections.FSharpList`1[System.Int32]
Run Code Online (Sandbox Code Playgroud)