代码之家  ›  专栏  ›  技术社区  ›  Wallace

什么时候使用f的类型defof<t>vs.typeof<t>?

f#
  •  10
  • Wallace  · 技术社区  · 7 年前

    有人能说明什么时候使用吗 typedefof<'T> VS typeof<'T> ?

    两个 typedefof<System.String> typeof<System.String> 返回相同的 Type 实例。

    但是,它们返回不同的实例和不同的信息 System.Collections.Generic.List<_> .

    我能想到 typedefof 作为一个新的和改进的 typeof ?我应该换成一直用 字体类型 ?还是比这更微妙?

    3 回复  |  直到 7 年前
        1
  •  9
  •   phoog    6 年前

    这应该说明两者的区别。当你使用 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
    

    因为 类型 只能返回构造类型, typedefof 如果需要表示泛型类型定义的类型对象,则需要。

        2
  •  10
  •   Aaron M. Eshbach    7 年前

    typeof 当你想得到 System.Type 给定类型的对象。 typedefof 当你想得到 系统类型 表示泛型类型的类型定义的。作为同时使用这两种方法的示例,假设您有一个名为 Generic<'a> ,并希望创建一个函数,该函数返回 系统类型 对象 Generic 任何给定类型的。

    type Generic<'a> = Value of 'a
    
    let makeGenericOf<'a> () = 
        typedefof<Generic<_>>.MakeGenericType(typeof<'a>)
    

    在这里,你可以使用 字体类型 函数获取类型定义,以及 类型 得到 'a 用于构造泛型 通用<'a> Type .

        3
  •  2
  •   Wallace    7 年前

    我真的很感谢Phoog,Aaron和Jrrishe的回答。以下是我所学到的,基于他们的回答和我自己的实验。

    有两个 Type 与泛型关联的实例。

    1. 有一个 类型 与具有特定类型参数的泛型关联。例如,有一个 类型 List<int> 和一个不同的 类型 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]"
      
    2. 有一个 类型 与泛型类型定义本身关联。例如,有一个 类型 List<'T> ,对于 列表<int> , 列表<字符串> 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]" 
      

    顺便说一下, 类型 类有一个实例方法 GetGenericTypeDefinition() . 这意味着,以下两个返回相同的实例:

        > Object.ReferenceEquals(typeof<List<int>>.GetGenericTypeDefinition(), typedefof<List<int>>);;
        val it : bool = true        
    

    如果你打电话给 typeof<List<_>> ?你回去吧 类型 定义 List<Object> ,正如phoog提到的。

    > 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
    

    另外,如果您希望后期绑定实例化泛型类型,可以使用 MakeGenericType(...) 亚伦提到的方法。

    > let myList = typedefof<List<_>>.MakeGenericType(typeof<int>);;
    val myList : Type = Microsoft.FSharp.Collections.FSharpList`1[System.Int32]