5

您不能创建包含泛型参数的类型的实例。

但是,它不是抽象的或接口。

我正在阅读 StructureMapTypeExtensions助手,我遇到了:

public static bool IsConcrete(this Type type)
{
    return (!type.IsAbstract && !type.IsInterface);
}

我对这种解释方式并不满意,因为似乎一个类型是具体的,那么应该有可能存在它的一个实例。例如,我很难考虑像typeof(List<>).MakeGenericType(typeof(List<>).MakeGenericType(typeof(List<>)))具体类型这样的东西。

我知道 C# 中的开放泛型类型和 C# 中的抽象类型在它们偏离具体化的方式上非常不同,但与此同时,它们两者都有一些基本的抽象。如果您认为抽象类和接口的参数是操作实现,则可以将抽象类和接口解释为参数化。然而,这有点离题了。

我真正想知道的是一种将这些概念与一致的语义统一起来的方法,这种语义不会让人觉得像谎言那样可憎的东西List<List<List<>>>可以是具体的。我们有一种通用的方式来描述这种区别吗?

4

4 回答 4

2

我不确定您的问题是否更多地是关于参数多态性与子类型多态性的哲学方面(我在类型理论方面知识不足,无法回答)。

我选择以下非常实用的方式阅读,希望是你想知道的:

鉴于“具体”意味着“我可以创建它的实例 [*]”,并且如果没有参数化,则无法创建泛型类型的实例,因此 IsConcrete 的给定定义未能考虑泛型类型。那么,如何以这样的方式扩展 IsConcrete

  • IsConcrete(typeof(List<>))是假的
  • IsConcrete(typeof(List<int>))是真的
  • IsConcrete(typeof(typeof(List<>).MakeGenericType(typeof(List<>).MakeGenericType(typeof(List<>))))是假的?

为此,您可以使用Type.ContainsGenericParameters

一个快速的 LinqPad 片段来演示:

var TListGen = typeof(List<>);
var TListInt = typeof(List<int>); // this would be "concrete" in the sense
                                  // that its generic arguments
                                  // are all parametrized
var TTest = typeof(List<>).MakeGenericType(typeof(List<>).MakeGenericType(typeof(List<>)));                                     


(!TListGen.ContainsGenericParameters).Dump(); // False
(!TListInt.ContainsGenericParameters).Dump(); // True
(!TTest.ContainsGenericParameters).Dump(); // False

* 有一些陷阱,例如具有私有构造函数的具体类型

于 2012-12-12T10:08:42.813 回答
1

我认为以下陈述并不“完全”正确:

您不能创建包含泛型参数的类型的实例

泛型类实际上是类的模板(不是对象)。除非将该模板转换为封闭类,否则无法创建实例(对象)。

但是,因为我们没有为通用模板指定类型,所以它没有将其定义为具体/抽象。我们可以创建泛型类型的实例,只要它不是抽象的(或接口)!

不确定这是否有帮助。

于 2012-12-12T05:03:46.893 回答
1

仅当指定参数类型时才指定(完整)泛型类型。可能你想说

如果不指定泛型参数,则无法创建类型的实例。

泛型类型很容易具体化。让我们有泛型 A 和 B:

class A<T>          // concrete generic type
{
}

abstract class B<T> // abstract generic type i.e. not concrete
{
}

A<int> a = new A<int>();
// not possible: B<int> b = new B<int>();
bool a1 = typeof(A<>).IsAbstract,       // false
    a2 = typeof(A<int>).IsAbstract,     // false
    b1 = typeof(B<>).IsAbstract,        // true
    b2 = typeof(B<int>).IsAbstract;     // true

在您的示例中, anyList<T>将是具体的,而List<>不是具体的 - 因为它不是真正的 type,您可以从中构造实例,它是一个泛型类型定义 typeof(List<>).IsGenericTypeDefinition == true

于 2012-12-12T07:19:14.050 回答
0

我认为“可以实例化”和“具体”之间是有区别的。

下面的类是具体的:

class Foo{
   private readonly int number;
   private Foo(int i ){
      number = i;
   }
}

我会说它是,但你不能创建它的实例。所以让我们扩展它:

public Bar{
  class Foo{
     private readonly int number;
     private Foo(int i){
        number = i;
     }
  }

  public static Foo Create(int i){
    return new Foo(i);     
  }
}

但这或多或少比以下具体:

public class Bar {
  class Foo<T>{
     private readonly T obj;
     private Foo(T obj){
          number = i;
     }
  }

  public static Foo<T> Create<T>(T obj){
     return new Foo<T>(obj);     
  }
}

要获取您编写的 Foo 的任一版本的实例Bar.Create(1)(或传递另一个参数)。

抽象类中是否缺少任何功能?它不一定是,但它肯定可以,所以我们不知道类的功能。对于泛型类型定义是否如此。不,这不对。某些功能可能会延迟到泛型类型的对象,但这是不同的。和Eg没有太大区别。使用策略模式:

interface IExecutor{
     void Execute();
}

public class Command{
     IExecutor _e;
     public Command(IExecutor e){
          _e = e;
     }

     public void Do(){
        _e.Execute();
     }
}


public class Command<T> where T : IExecutor{
     public Command(T e){
          _e = e;
     }

     public void Do(){
        _e.Execute();
     }
}

这两个类中的任何一个比另一个更具体/通用吗?当谈到一个算法的具体实现时,你有什么可以说的吗?

于 2012-12-12T12:30:22.580 回答