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

ジェネリック型は、パラメトリック型が指定されている場合にのみ指定 (完全) されます。言いたかったんでしょうね

ジェネリック パラメーターを指定せずに型のインスタンスを作成することはできません。

ジェネリック型は簡単に具象化できます。ジェネリック型 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();
     }
}

これらの 2 つのクラスのいずれかが、他のクラスより具体的/一般的ですか? もう一方については言えないアルゴリズムの具体的な実装に関して、一方について言えることはありますか?

于 2012-12-12T12:30:22.580 に答える