C# 开放泛型类型被认为是具体的吗?我们如何通过参数化来限定抽象?

C# 开放泛型类型被认为是具体的吗?我们如何通过参数化来限定抽象?,c#,generics,interface,abstract-class,abstract,C#,Generics,Interface,Abstract Class,Abstract,无法创建包含泛型参数的类型的实例 然而,它不是抽象的或接口 我正在阅读StructureMapTypeExtensionshelpers,我发现: public static bool IsConcrete(this Type type) { return (!type.IsAbstract && !type.IsInterface); } 我对它的解释方式不是很满意,因为在我看来,如果一个类型是具体的,那么应该有一个实例。例如,我很难将typeof(List)、Mak

无法创建包含泛型参数的类型的实例

然而,它不是抽象的或接口

我正在阅读StructureMap
TypeExtensions
helpers,我发现:

public static bool IsConcrete(this Type type)
{
    return (!type.IsAbstract && !type.IsInterface);
}
我对它的解释方式不是很满意,因为在我看来,如果一个类型是具体的,那么应该有一个实例。例如,我很难将
typeof(List)、MakeGenericType(typeof(List)、MakeGenericType(typeof(List))
视为具体类型

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


我真正想知道的是,如何将这些概念与一致的语义统一起来,而不是像
List
这样令人厌恶的东西可以具体化的谎言。我们是否有一个通用的方法来描述这种区别?

我认为下面的说法并不“完全”正确:

无法创建包含泛型的类型的实例 参数

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

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


不确定这是否有帮助。

仅当指定了参数化类型时,才会指定(完成)泛型类型。也许你想说

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

泛型类型可以很容易地具体化。让我们来看看泛型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
A类//具体泛型类型
{
}
抽象类B//抽象泛型类型,即非具体类型
{
}
A=新的A();
//不可能:B=新B();
bool a1=typeof(A).isastract,//false
a2=类型(A).IsaStract,//假
b1=类型(B)。IsAbstract,//true
b2=类型(B)。IsaStract;//真的

在您的示例中,任何
List
都是具体的,而
List
不是-因为,您从中构造实例,它是
typeof(List)。IsGenericTypeDefinition==true
我不确定您的问题是否更多地是关于参数多态性与子类型多态性的哲学方面(我在类型理论方面的知识还不足以回答这个问题)

我选择以一种非常实际的方式阅读它,如下所示,希望它是您想要知道的:

鉴于“concrete”意味着“我可以创建它的实例[*]”,并且如果不是泛型类型的实例,您就不能创建泛型类型的实例,给定的IsConcrete定义没有考虑泛型类型。那么,您如何扩展IsConcrete,使其

  • IsConcrete(typeof(List))
    为false
  • IsConcrete(typeof(List))
    为true
  • IsConcrete(typeof(列表)。MakeGenericType(列表)。MakeGenericType(列表))
    为false
你可以用

要演示的快速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
var TListGen=typeof(列表);
var TListInt=typeof(List);//这在某种意义上是“具体的”
//这是一般性的论点
//都参数化了吗
var TTest=typeof(List).MakeGenericType(typeof(List).MakeGenericType(typeof(List));
(!TListGen.ContainsGenericParameters).Dump();//False
(!tlistent.ContainsGenericParameters).Dump();//True
(!TTest.ContainsGenericParameters).Dump();//False

*对于一些gotchas,例如具有私有构造函数的具体类型,我认为“可以实例化”和“具体”之间有区别

是以下等级的混凝土:

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);     
  }
}

这两个类中有哪一个比另一个更具体/通用?当涉及到一个算法的具体实现时,你能对其中一个说些什么吗?你可能应该选择一个标记来替换为C#(如果有什么需要引起更多注意的话)。@PaulBellora-有道理“我真正想知道的是,如何将这些概念与一致的语义统一起来,而不是像
列表
这样令人厌恶的东西可以具体化的谎言。"--FWWW,我不认为它比“代码> >清单更多的是一个abyimime:<代码> t>代码>是一个静态类,它肯定是具体的:您可以创建这样一个列表,并且可以将<代码> null <代码>添加到该列表中。但是,您正确地认为,<代码>列表在您的定义中是不具体的:它不能被实例化。@帽子…所以我试过了…你是对的,很奇怪。
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();
     }
}